1 /*-------------------------------------------------------------------------
4 * Contains functions which control the execution of the POSTGRES utility
5 * commands. At one time acted as an interface between the Lisp and C
8 * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.228 2004/08/29 05:06:49 momjian Exp $
15 *-------------------------------------------------------------------------
19 #include "access/heapam.h"
20 #include "catalog/catalog.h"
21 #include "catalog/namespace.h"
22 #include "catalog/pg_shadow.h"
23 #include "commands/alter.h"
24 #include "commands/async.h"
25 #include "commands/cluster.h"
26 #include "commands/comment.h"
27 #include "commands/copy.h"
28 #include "commands/conversioncmds.h"
29 #include "commands/dbcommands.h"
30 #include "commands/defrem.h"
31 #include "commands/explain.h"
32 #include "commands/lockcmds.h"
33 #include "commands/portalcmds.h"
34 #include "commands/prepare.h"
35 #include "commands/proclang.h"
36 #include "commands/schemacmds.h"
37 #include "commands/sequence.h"
38 #include "commands/tablecmds.h"
39 #include "commands/tablespace.h"
40 #include "commands/trigger.h"
41 #include "commands/typecmds.h"
42 #include "commands/user.h"
43 #include "commands/vacuum.h"
44 #include "commands/view.h"
45 #include "miscadmin.h"
46 #include "nodes/makefuncs.h"
47 #include "parser/parse_expr.h"
48 #include "parser/parse_type.h"
49 #include "postmaster/bgwriter.h"
50 #include "rewrite/rewriteDefine.h"
51 #include "rewrite/rewriteRemove.h"
52 #include "storage/fd.h"
53 #include "tcop/pquery.h"
54 #include "tcop/utility.h"
55 #include "utils/acl.h"
56 #include "utils/guc.h"
57 #include "utils/lsyscache.h"
58 #include "utils/syscache.h"
62 * Error-checking support for DROP commands
69 const char *nonexistent_msg;
71 const char *drophint_msg;
74 static const struct msgstrings msgstringarray[] = {
76 ERRCODE_UNDEFINED_TABLE,
77 gettext_noop("table \"%s\" does not exist"),
78 gettext_noop("\"%s\" is not a table"),
79 gettext_noop("Use DROP TABLE to remove a table.")},
81 ERRCODE_UNDEFINED_TABLE,
82 gettext_noop("sequence \"%s\" does not exist"),
83 gettext_noop("\"%s\" is not a sequence"),
84 gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
86 ERRCODE_UNDEFINED_TABLE,
87 gettext_noop("view \"%s\" does not exist"),
88 gettext_noop("\"%s\" is not a view"),
89 gettext_noop("Use DROP VIEW to remove a view.")},
91 ERRCODE_UNDEFINED_OBJECT,
92 gettext_noop("index \"%s\" does not exist"),
93 gettext_noop("\"%s\" is not an index"),
94 gettext_noop("Use DROP INDEX to remove an index.")},
95 {RELKIND_COMPOSITE_TYPE,
96 ERRCODE_UNDEFINED_OBJECT,
97 gettext_noop("type \"%s\" does not exist"),
98 gettext_noop("\"%s\" is not a type"),
99 gettext_noop("Use DROP TYPE to remove a type.")},
100 {'\0', 0, NULL, NULL, NULL}
105 * Emit the right error message for a "DROP" command issued on a
106 * relation of the wrong type
109 DropErrorMsgWrongType(char *relname, char wrongkind, char rightkind)
111 const struct msgstrings *rentry;
112 const struct msgstrings *wentry;
114 for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
115 if (rentry->kind == rightkind)
117 Assert(rentry->kind != '\0');
119 for (wentry = msgstringarray; wentry->kind != '\0'; wentry++)
120 if (wentry->kind == wrongkind)
122 /* wrongkind could be something we don't have in our table... */
125 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
126 errmsg(rentry->nota_msg, relname),
127 (wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
131 * Emit the right error message for a "DROP" command issued on a
132 * non-existent relation
135 DropErrorMsgNonExistent(RangeVar *rel, char rightkind)
137 const struct msgstrings *rentry;
139 for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
141 if (rentry->kind == rightkind)
143 (errcode(rentry->nonexistent_code),
144 errmsg(rentry->nonexistent_msg, rel->relname)));
147 Assert(false); /* Should be impossible */
151 CheckDropPermissions(RangeVar *rel, char rightkind)
155 Form_pg_class classform;
157 relOid = RangeVarGetRelid(rel, true);
158 if (!OidIsValid(relOid))
159 DropErrorMsgNonExistent(rel, rightkind);
161 tuple = SearchSysCache(RELOID,
162 ObjectIdGetDatum(relOid),
164 if (!HeapTupleIsValid(tuple))
165 elog(ERROR, "cache lookup failed for relation %u", relOid);
167 classform = (Form_pg_class) GETSTRUCT(tuple);
169 if (classform->relkind != rightkind)
170 DropErrorMsgWrongType(rel->relname, classform->relkind,
173 /* Allow DROP to either table owner or schema owner */
174 if (!pg_class_ownercheck(relOid, GetUserId()) &&
175 !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
176 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
179 if (!allowSystemTableMods && IsSystemClass(classform))
181 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
182 errmsg("permission denied: \"%s\" is a system catalog",
185 ReleaseSysCache(tuple);
189 * Verify user has ownership of specified relation, else ereport.
191 * If noCatalogs is true then we also deny access to system catalogs,
192 * except when allowSystemTableMods is true.
195 CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
200 relOid = RangeVarGetRelid(rel, false);
201 tuple = SearchSysCache(RELOID,
202 ObjectIdGetDatum(relOid),
204 if (!HeapTupleIsValid(tuple)) /* should not happen */
205 elog(ERROR, "cache lookup failed for relation %u", relOid);
207 if (!pg_class_ownercheck(relOid, GetUserId()))
208 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
213 if (!allowSystemTableMods &&
214 IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
216 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
217 errmsg("permission denied: \"%s\" is a system catalog",
221 ReleaseSysCache(tuple);
226 check_xact_readonly(Node *parsetree)
232 * Note: Commands that need to do more complicated checking are
236 switch (nodeTag(parsetree))
238 case T_AlterDatabaseSetStmt:
239 case T_AlterDomainStmt:
240 case T_AlterGroupStmt:
241 case T_AlterOwnerStmt:
243 case T_AlterTableStmt:
244 case T_AlterUserStmt:
245 case T_AlterUserSetStmt:
249 case T_CreateCastStmt:
250 case T_CreateConversionStmt:
252 case T_CreateDomainStmt:
253 case T_CreateFunctionStmt:
254 case T_CreateGroupStmt:
256 case T_CreatePLangStmt:
257 case T_CreateOpClassStmt:
259 case T_CreateSchemaStmt:
260 case T_CreateSeqStmt:
262 case T_CreateTableSpaceStmt:
263 case T_CreateTrigStmt:
264 case T_CompositeTypeStmt:
265 case T_CreateUserStmt:
267 case T_RemoveAggrStmt:
271 case T_DropTableSpaceStmt:
272 case T_RemoveFuncStmt:
273 case T_DropGroupStmt:
274 case T_DropPLangStmt:
275 case T_RemoveOperStmt:
276 case T_RemoveOpClassStmt:
277 case T_DropPropertyStmt:
282 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
283 errmsg("transaction is read-only")));
294 * general utility function invoker
296 * parsetree: the parse tree for the utility statement
297 * params: parameters to use during execution (currently only used by DECLARE)
298 * dest: where to send results
299 * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
300 * in which to store a command completion status string.
302 * completionTag is only set nonempty if we want to return a nondefault
303 * status (currently, only used for MOVE/FETCH).
305 * completionTag may be NULL if caller doesn't want a status string.
308 ProcessUtility(Node *parsetree,
309 ParamListInfo params,
313 check_xact_readonly(parsetree);
316 completionTag[0] = '\0';
318 switch (nodeTag(parsetree))
321 * ******************** transactions ********************
323 case T_TransactionStmt:
325 TransactionStmt *stmt = (TransactionStmt *) parsetree;
330 * START TRANSACTION, as defined by SQL99:
331 * Identical to BEGIN. Same code for both.
333 case TRANS_STMT_BEGIN:
334 case TRANS_STMT_START:
338 BeginTransactionBlock();
339 foreach(lc, stmt->options)
341 DefElem *item = (DefElem *) lfirst(lc);
343 if (strcmp(item->defname, "transaction_isolation") == 0)
344 SetPGVariable("transaction_isolation",
345 list_make1(item->arg),
347 else if (strcmp(item->defname, "transaction_read_only") == 0)
348 SetPGVariable("transaction_read_only",
349 list_make1(item->arg),
355 case TRANS_STMT_COMMIT:
356 if (!EndTransactionBlock())
358 /* report unsuccessful commit in completionTag */
360 strcpy(completionTag, "ROLLBACK");
364 case TRANS_STMT_ROLLBACK:
365 UserAbortTransactionBlock();
368 case TRANS_STMT_SAVEPOINT:
373 RequireTransactionChain((void *) stmt, "SAVEPOINT");
375 foreach(cell, stmt->options)
377 DefElem *elem = lfirst(cell);
379 if (strcmp(elem->defname, "savepoint_name") == 0)
380 name = strVal(elem->arg);
383 Assert(PointerIsValid(name));
385 DefineSavepoint(name);
389 case TRANS_STMT_RELEASE:
390 RequireTransactionChain((void *) stmt, "RELEASE SAVEPOINT");
391 ReleaseSavepoint(stmt->options);
394 case TRANS_STMT_ROLLBACK_TO:
395 RequireTransactionChain((void *) stmt, "ROLLBACK TO SAVEPOINT");
396 RollbackToSavepoint(stmt->options);
399 * CommitTransactionCommand is in charge of
400 * re-defining the savepoint again
408 * Portal (cursor) manipulation
410 case T_DeclareCursorStmt:
411 PerformCursorOpen((DeclareCursorStmt *) parsetree, params);
414 case T_ClosePortalStmt:
416 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
418 PerformPortalClose(stmt->portalname);
423 PerformPortalFetch((FetchStmt *) parsetree, dest,
428 * relation and attribute manipulation
430 case T_CreateSchemaStmt:
431 CreateSchemaCommand((CreateSchemaStmt *) parsetree);
438 relOid = DefineRelation((CreateStmt *) parsetree,
442 * Let AlterTableCreateToastTable decide if this one needs
443 * a secondary relation too.
445 CommandCounterIncrement();
446 AlterTableCreateToastTable(relOid, true);
450 case T_CreateTableSpaceStmt:
451 CreateTableSpace((CreateTableSpaceStmt *) parsetree);
454 case T_DropTableSpaceStmt:
455 DropTableSpace((DropTableSpaceStmt *) parsetree);
460 DropStmt *stmt = (DropStmt *) parsetree;
463 foreach(arg, stmt->objects)
465 List *names = (List *) lfirst(arg);
468 switch (stmt->removeType)
471 rel = makeRangeVarFromNameList(names);
472 CheckDropPermissions(rel, RELKIND_RELATION);
473 RemoveRelation(rel, stmt->behavior);
476 case OBJECT_SEQUENCE:
477 rel = makeRangeVarFromNameList(names);
478 CheckDropPermissions(rel, RELKIND_SEQUENCE);
479 RemoveRelation(rel, stmt->behavior);
483 rel = makeRangeVarFromNameList(names);
484 CheckDropPermissions(rel, RELKIND_VIEW);
485 RemoveView(rel, stmt->behavior);
489 rel = makeRangeVarFromNameList(names);
490 CheckDropPermissions(rel, RELKIND_INDEX);
491 RemoveIndex(rel, stmt->behavior);
495 /* RemoveType does its own permissions checks */
496 RemoveType(names, stmt->behavior);
502 * RemoveDomain does its own permissions
505 RemoveDomain(names, stmt->behavior);
508 case OBJECT_CONVERSION:
509 DropConversionCommand(names, stmt->behavior);
515 * RemoveSchema does its own permissions
518 RemoveSchema(names, stmt->behavior);
522 elog(ERROR, "unrecognized drop object type: %d",
523 (int) stmt->removeType);
528 * We used to need to do CommandCounterIncrement()
529 * here, but now it's done inside performDeletion().
537 TruncateStmt *stmt = (TruncateStmt *) parsetree;
539 TruncateRelation(stmt->relation);
544 CommentObject((CommentStmt *) parsetree);
548 DoCopy((CopyStmt *) parsetree);
552 PrepareQuery((PrepareStmt *) parsetree);
556 ExecuteQuery((ExecuteStmt *) parsetree, dest, completionTag);
559 case T_DeallocateStmt:
560 DeallocateQuery((DeallocateStmt *) parsetree);
567 ExecRenameStmt((RenameStmt *) parsetree);
570 case T_AlterOwnerStmt:
571 ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
574 case T_AlterTableStmt:
575 AlterTable((AlterTableStmt *) parsetree);
578 case T_AlterDomainStmt:
580 AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
583 * Some or all of these functions are recursive to cover
584 * inherited things, so permission checks are done there.
586 switch (stmt->subtype)
588 case 'T': /* ALTER DOMAIN DEFAULT */
591 * Recursively alter column default for table and,
592 * if requested, for descendants
594 AlterDomainDefault(stmt->typename,
597 case 'N': /* ALTER DOMAIN DROP NOT NULL */
598 AlterDomainNotNull(stmt->typename,
601 case 'O': /* ALTER DOMAIN SET NOT NULL */
602 AlterDomainNotNull(stmt->typename,
605 case 'C': /* ADD CONSTRAINT */
606 AlterDomainAddConstraint(stmt->typename,
609 case 'X': /* DROP CONSTRAINT */
610 AlterDomainDropConstraint(stmt->typename,
615 elog(ERROR, "unrecognized alter domain type: %d",
616 (int) stmt->subtype);
624 ExecuteGrantStmt((GrantStmt *) parsetree);
628 * ******************************** object creation /
629 * destruction ********************************
634 DefineStmt *stmt = (DefineStmt *) parsetree;
638 case OBJECT_AGGREGATE:
639 DefineAggregate(stmt->defnames, stmt->definition);
641 case OBJECT_OPERATOR:
642 DefineOperator(stmt->defnames, stmt->definition);
645 DefineType(stmt->defnames, stmt->definition);
648 elog(ERROR, "unrecognized define stmt type: %d",
655 case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
657 CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
659 DefineCompositeType(stmt->typevar, stmt->coldeflist);
663 case T_ViewStmt: /* CREATE VIEW */
665 ViewStmt *stmt = (ViewStmt *) parsetree;
667 DefineView(stmt->view, stmt->query, stmt->replace);
671 case T_CreateFunctionStmt: /* CREATE FUNCTION */
672 CreateFunction((CreateFunctionStmt *) parsetree);
675 case T_IndexStmt: /* CREATE INDEX */
677 IndexStmt *stmt = (IndexStmt *) parsetree;
679 CheckRelationOwnership(stmt->relation, true);
681 DefineIndex(stmt->relation, /* relation */
682 stmt->idxname, /* index name */
683 stmt->accessMethod, /* am name */
685 stmt->indexParams, /* parameters */
686 (Expr *) stmt->whereClause,
691 false, /* is_alter_table */
692 true, /* check_rights */
693 false, /* skip_build */
698 case T_RuleStmt: /* CREATE RULE */
699 DefineQueryRewrite((RuleStmt *) parsetree);
702 case T_CreateSeqStmt:
703 DefineSequence((CreateSeqStmt *) parsetree);
707 AlterSequence((AlterSeqStmt *) parsetree);
710 case T_RemoveAggrStmt:
711 RemoveAggregate((RemoveAggrStmt *) parsetree);
714 case T_RemoveFuncStmt:
715 RemoveFunction((RemoveFuncStmt *) parsetree);
718 case T_RemoveOperStmt:
719 RemoveOperator((RemoveOperStmt *) parsetree);
723 createdb((CreatedbStmt *) parsetree);
726 case T_AlterDatabaseSetStmt:
727 AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
732 DropdbStmt *stmt = (DropdbStmt *) parsetree;
734 dropdb(stmt->dbname);
738 /* Query-level asynchronous notification */
741 NotifyStmt *stmt = (NotifyStmt *) parsetree;
743 Async_Notify(stmt->relation->relname);
749 ListenStmt *stmt = (ListenStmt *) parsetree;
751 Async_Listen(stmt->relation->relname, MyProcPid);
757 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
759 Async_Unlisten(stmt->relation->relname, MyProcPid);
765 LoadStmt *stmt = (LoadStmt *) parsetree;
767 closeAllVfds(); /* probably not necessary... */
768 load_file(stmt->filename);
773 cluster((ClusterStmt *) parsetree);
777 vacuum((VacuumStmt *) parsetree);
781 ExplainQuery((ExplainStmt *) parsetree, dest);
784 case T_VariableSetStmt:
786 VariableSetStmt *n = (VariableSetStmt *) parsetree;
789 * Special cases for special SQL syntax that effectively
790 * sets more than one variable per statement.
792 if (strcmp(n->name, "TRANSACTION") == 0)
796 foreach(head, n->args)
798 DefElem *item = (DefElem *) lfirst(head);
800 if (strcmp(item->defname, "transaction_isolation") == 0)
801 SetPGVariable("transaction_isolation",
802 list_make1(item->arg), n->is_local);
803 else if (strcmp(item->defname, "transaction_read_only") == 0)
804 SetPGVariable("transaction_read_only",
805 list_make1(item->arg), n->is_local);
808 else if (strcmp(n->name, "SESSION CHARACTERISTICS") == 0)
812 foreach(head, n->args)
814 DefElem *item = (DefElem *) lfirst(head);
816 if (strcmp(item->defname, "transaction_isolation") == 0)
817 SetPGVariable("default_transaction_isolation",
818 list_make1(item->arg), n->is_local);
819 else if (strcmp(item->defname, "transaction_read_only") == 0)
820 SetPGVariable("default_transaction_read_only",
821 list_make1(item->arg), n->is_local);
825 SetPGVariable(n->name, n->args, n->is_local);
829 case T_VariableShowStmt:
831 VariableShowStmt *n = (VariableShowStmt *) parsetree;
833 GetPGVariable(n->name, dest);
837 case T_VariableResetStmt:
839 VariableResetStmt *n = (VariableResetStmt *) parsetree;
841 ResetPGVariable(n->name);
845 case T_CreateTrigStmt:
846 CreateTrigger((CreateTrigStmt *) parsetree, false);
849 case T_DropPropertyStmt:
851 DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
854 relId = RangeVarGetRelid(stmt->relation, false);
856 switch (stmt->removeType)
859 /* RemoveRewriteRule checks permissions */
860 RemoveRewriteRule(relId, stmt->property,
864 /* DropTrigger checks permissions */
865 DropTrigger(relId, stmt->property,
869 elog(ERROR, "unrecognized object type: %d",
870 (int) stmt->removeType);
876 case T_CreatePLangStmt:
877 CreateProceduralLanguage((CreatePLangStmt *) parsetree);
880 case T_DropPLangStmt:
881 DropProceduralLanguage((DropPLangStmt *) parsetree);
885 * ******************************** DOMAIN statements ****
887 case T_CreateDomainStmt:
888 DefineDomain((CreateDomainStmt *) parsetree);
892 * ******************************** USER statements ****
894 case T_CreateUserStmt:
895 CreateUser((CreateUserStmt *) parsetree);
898 case T_AlterUserStmt:
899 AlterUser((AlterUserStmt *) parsetree);
902 case T_AlterUserSetStmt:
903 AlterUserSet((AlterUserSetStmt *) parsetree);
907 DropUser((DropUserStmt *) parsetree);
911 LockTableCommand((LockStmt *) parsetree);
914 case T_ConstraintsSetStmt:
915 DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
918 case T_CreateGroupStmt:
919 CreateGroup((CreateGroupStmt *) parsetree);
922 case T_AlterGroupStmt:
923 AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
926 case T_DropGroupStmt:
927 DropGroup((DropGroupStmt *) parsetree);
930 case T_CheckPointStmt:
933 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
934 errmsg("must be superuser to do CHECKPOINT")));
935 RequestCheckpoint(true);
940 ReindexStmt *stmt = (ReindexStmt *) parsetree;
945 ReindexIndex(stmt->relation, stmt->force);
948 ReindexTable(stmt->relation, stmt->force);
950 case OBJECT_DATABASE:
951 ReindexDatabase(stmt->name, stmt->force, false);
954 elog(ERROR, "unrecognized object type: %d",
962 case T_CreateConversionStmt:
963 CreateConversionCommand((CreateConversionStmt *) parsetree);
966 case T_CreateCastStmt:
967 CreateCast((CreateCastStmt *) parsetree);
971 DropCast((DropCastStmt *) parsetree);
974 case T_CreateOpClassStmt:
975 DefineOpClass((CreateOpClassStmt *) parsetree);
978 case T_RemoveOpClassStmt:
979 RemoveOpClass((RemoveOpClassStmt *) parsetree);
983 elog(ERROR, "unrecognized node type: %d",
984 (int) nodeTag(parsetree));
990 * UtilityReturnsTuples
991 * Return "true" if this utility statement will send output to the
994 * Generally, there should be a case here for each case in ProcessUtility
995 * where "dest" is passed on.
998 UtilityReturnsTuples(Node *parsetree)
1000 switch (nodeTag(parsetree))
1004 FetchStmt *stmt = (FetchStmt *) parsetree;
1009 portal = GetPortalByName(stmt->portalname);
1010 if (!PortalIsValid(portal))
1011 return false; /* not our business to raise error */
1012 return portal->tupDesc ? true : false;
1017 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
1018 PreparedStatement *entry;
1022 entry = FetchPreparedStatement(stmt->name, false);
1024 return false; /* not our business to raise error */
1025 switch (ChoosePortalStrategy(entry->query_list))
1027 case PORTAL_ONE_SELECT:
1029 case PORTAL_UTIL_SELECT:
1031 case PORTAL_MULTI_QUERY:
1032 /* will not return tuples */
1041 case T_VariableShowStmt:
1050 * UtilityTupleDescriptor
1051 * Fetch the actual output tuple descriptor for a utility statement
1052 * for which UtilityReturnsTuples() previously returned "true".
1054 * The returned descriptor is created in (or copied into) the current memory
1058 UtilityTupleDescriptor(Node *parsetree)
1060 switch (nodeTag(parsetree))
1064 FetchStmt *stmt = (FetchStmt *) parsetree;
1069 portal = GetPortalByName(stmt->portalname);
1070 if (!PortalIsValid(portal))
1071 return NULL; /* not our business to raise error */
1072 return CreateTupleDescCopy(portal->tupDesc);
1077 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
1078 PreparedStatement *entry;
1082 entry = FetchPreparedStatement(stmt->name, false);
1084 return NULL; /* not our business to raise error */
1085 return FetchPreparedStatementResultDesc(entry);
1089 return ExplainResultDesc((ExplainStmt *) parsetree);
1091 case T_VariableShowStmt:
1093 VariableShowStmt *n = (VariableShowStmt *) parsetree;
1095 return GetPGVariableResultDesc(n->name);
1106 * utility to get a string representation of the
1107 * command operation, given a raw (un-analyzed) parsetree.
1109 * This must handle all raw command types, but since the vast majority
1110 * of 'em are utility commands, it seems sensible to keep it here.
1112 * NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
1113 * Also, the result must point at a true constant (permanent storage).
1116 CreateCommandTag(Node *parsetree)
1120 switch (nodeTag(parsetree))
1138 case T_TransactionStmt:
1140 TransactionStmt *stmt = (TransactionStmt *) parsetree;
1144 case TRANS_STMT_BEGIN:
1148 case TRANS_STMT_START:
1149 tag = "START TRANSACTION";
1152 case TRANS_STMT_COMMIT:
1156 case TRANS_STMT_ROLLBACK:
1157 case TRANS_STMT_ROLLBACK_TO:
1161 case TRANS_STMT_SAVEPOINT:
1165 case TRANS_STMT_RELEASE:
1176 case T_DeclareCursorStmt:
1177 tag = "DECLARE CURSOR";
1180 case T_ClosePortalStmt:
1181 tag = "CLOSE CURSOR";
1186 FetchStmt *stmt = (FetchStmt *) parsetree;
1188 tag = (stmt->ismove) ? "MOVE" : "FETCH";
1192 case T_CreateDomainStmt:
1193 tag = "CREATE DOMAIN";
1196 case T_CreateSchemaStmt:
1197 tag = "CREATE SCHEMA";
1201 tag = "CREATE TABLE";
1204 case T_CreateTableSpaceStmt:
1205 tag = "CREATE TABLESPACE";
1208 case T_DropTableSpaceStmt:
1209 tag = "DROP TABLESPACE";
1213 switch (((DropStmt *) parsetree)->removeType)
1218 case OBJECT_SEQUENCE:
1219 tag = "DROP SEQUENCE";
1231 tag = "DROP DOMAIN";
1233 case OBJECT_CONVERSION:
1234 tag = "DROP CONVERSION";
1237 tag = "DROP SCHEMA";
1244 case T_TruncateStmt:
1245 tag = "TRUNCATE TABLE";
1257 switch (((RenameStmt *) parsetree)->renameType)
1259 case OBJECT_AGGREGATE:
1260 tag = "ALTER AGGREGATE";
1262 case OBJECT_CONVERSION:
1263 tag = "ALTER CONVERSION";
1265 case OBJECT_DATABASE:
1266 tag = "ALTER DATABASE";
1268 case OBJECT_FUNCTION:
1269 tag = "ALTER FUNCTION";
1272 tag = "ALTER GROUP";
1275 tag = "ALTER INDEX";
1277 case OBJECT_LANGUAGE:
1278 tag = "ALTER LANGUAGE";
1280 case OBJECT_OPCLASS:
1281 tag = "ALTER OPERATOR CLASS";
1284 tag = "ALTER SCHEMA";
1286 case OBJECT_TABLESPACE:
1287 tag = "ALTER TABLESPACE";
1289 case OBJECT_TRIGGER:
1290 tag = "ALTER TRIGGER";
1296 tag = "ALTER TABLE";
1300 case T_AlterOwnerStmt:
1301 switch (((AlterOwnerStmt *) parsetree)->objectType)
1303 case OBJECT_AGGREGATE:
1304 tag = "ALTER AGGREGATE";
1306 case OBJECT_CONVERSION:
1307 tag = "ALTER CONVERSION";
1309 case OBJECT_DATABASE:
1310 tag = "ALTER DATABASE";
1313 tag = "ALTER DOMAIN";
1315 case OBJECT_FUNCTION:
1316 tag = "ALTER FUNCTION";
1318 case OBJECT_OPERATOR:
1319 tag = "ALTER OPERATOR";
1321 case OBJECT_OPCLASS:
1322 tag = "ALTER OPERATOR CLASS";
1325 tag = "ALTER SCHEMA";
1327 case OBJECT_TABLESPACE:
1328 tag = "ALTER TABLESPACE";
1334 tag = "ALTER TABLE";
1338 case T_AlterTableStmt:
1340 AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
1343 * We might be supporting ALTER INDEX here, so set the
1344 * completion table appropriately. Catch all other
1345 * possibilities with ALTER TABLE
1348 if (stmt->relkind == OBJECT_INDEX)
1349 tag = "ALTER INDEX";
1351 tag = "ALTER TABLE";
1354 case T_AlterDomainStmt:
1355 tag = "ALTER DOMAIN";
1360 GrantStmt *stmt = (GrantStmt *) parsetree;
1362 tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
1367 switch (((DefineStmt *) parsetree)->kind)
1369 case OBJECT_AGGREGATE:
1370 tag = "CREATE AGGREGATE";
1372 case OBJECT_OPERATOR:
1373 tag = "CREATE OPERATOR";
1376 tag = "CREATE TYPE";
1383 case T_CompositeTypeStmt:
1384 tag = "CREATE TYPE";
1388 tag = "CREATE VIEW";
1391 case T_CreateFunctionStmt:
1392 tag = "CREATE FUNCTION";
1396 tag = "CREATE INDEX";
1400 tag = "CREATE RULE";
1403 case T_CreateSeqStmt:
1404 tag = "CREATE SEQUENCE";
1407 case T_AlterSeqStmt:
1408 tag = "ALTER SEQUENCE";
1411 case T_RemoveAggrStmt:
1412 tag = "DROP AGGREGATE";
1415 case T_RemoveFuncStmt:
1416 tag = "DROP FUNCTION";
1419 case T_RemoveOperStmt:
1420 tag = "DROP OPERATOR";
1423 case T_CreatedbStmt:
1424 tag = "CREATE DATABASE";
1427 case T_AlterDatabaseSetStmt:
1428 tag = "ALTER DATABASE";
1432 tag = "DROP DATABASE";
1443 case T_UnlistenStmt:
1456 if (((VacuumStmt *) parsetree)->vacuum)
1466 case T_VariableSetStmt:
1470 case T_VariableShowStmt:
1474 case T_VariableResetStmt:
1478 case T_CreateTrigStmt:
1479 tag = "CREATE TRIGGER";
1482 case T_DropPropertyStmt:
1483 switch (((DropPropertyStmt *) parsetree)->removeType)
1485 case OBJECT_TRIGGER:
1486 tag = "DROP TRIGGER";
1496 case T_CreatePLangStmt:
1497 tag = "CREATE LANGUAGE";
1500 case T_DropPLangStmt:
1501 tag = "DROP LANGUAGE";
1504 case T_CreateUserStmt:
1505 tag = "CREATE USER";
1508 case T_AlterUserStmt:
1512 case T_AlterUserSetStmt:
1516 case T_DropUserStmt:
1524 case T_ConstraintsSetStmt:
1525 tag = "SET CONSTRAINTS";
1528 case T_CreateGroupStmt:
1529 tag = "CREATE GROUP";
1532 case T_AlterGroupStmt:
1533 tag = "ALTER GROUP";
1536 case T_DropGroupStmt:
1540 case T_CheckPointStmt:
1548 case T_CreateConversionStmt:
1549 tag = "CREATE CONVERSION";
1552 case T_CreateCastStmt:
1553 tag = "CREATE CAST";
1556 case T_DropCastStmt:
1560 case T_CreateOpClassStmt:
1561 tag = "CREATE OPERATOR CLASS";
1564 case T_RemoveOpClassStmt:
1565 tag = "DROP OPERATOR CLASS";
1576 case T_DeallocateStmt:
1581 elog(WARNING, "unrecognized node type: %d",
1582 (int) nodeTag(parsetree));