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-2005, 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.250 2005/11/29 01:25:49 tgl Exp $
15 *-------------------------------------------------------------------------
19 #include "access/heapam.h"
20 #include "access/twophase.h"
21 #include "catalog/catalog.h"
22 #include "catalog/namespace.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;
70 const char *skipping_msg;
72 const char *drophint_msg;
75 static const struct msgstrings msgstringarray[] = {
77 ERRCODE_UNDEFINED_TABLE,
78 gettext_noop("table \"%s\" does not exist"),
79 gettext_noop("table \"%s\" does not exist, skipping"),
80 gettext_noop("\"%s\" is not a table"),
81 gettext_noop("Use DROP TABLE to remove a table.")},
83 ERRCODE_UNDEFINED_TABLE,
84 gettext_noop("sequence \"%s\" does not exist"),
85 gettext_noop("sequence \"%s\" does not exist, skipping"),
86 gettext_noop("\"%s\" is not a sequence"),
87 gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
89 ERRCODE_UNDEFINED_TABLE,
90 gettext_noop("view \"%s\" does not exist"),
91 gettext_noop("view \"%s\" does not exist, skipping"),
92 gettext_noop("\"%s\" is not a view"),
93 gettext_noop("Use DROP VIEW to remove a view.")},
95 ERRCODE_UNDEFINED_OBJECT,
96 gettext_noop("index \"%s\" does not exist"),
97 gettext_noop("index \"%s\" does not exist, skipping"),
98 gettext_noop("\"%s\" is not an index"),
99 gettext_noop("Use DROP INDEX to remove an index.")},
100 {RELKIND_COMPOSITE_TYPE,
101 ERRCODE_UNDEFINED_OBJECT,
102 gettext_noop("type \"%s\" does not exist"),
103 gettext_noop("type \"%s\" does not exist, skipping"),
104 gettext_noop("\"%s\" is not a type"),
105 gettext_noop("Use DROP TYPE to remove a type.")},
106 {'\0', 0, NULL, NULL, NULL}
111 * Emit the right error message for a "DROP" command issued on a
112 * relation of the wrong type
115 DropErrorMsgWrongType(char *relname, char wrongkind, char rightkind)
117 const struct msgstrings *rentry;
118 const struct msgstrings *wentry;
120 for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
121 if (rentry->kind == rightkind)
123 Assert(rentry->kind != '\0');
125 for (wentry = msgstringarray; wentry->kind != '\0'; wentry++)
126 if (wentry->kind == wrongkind)
128 /* wrongkind could be something we don't have in our table... */
131 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
132 errmsg(rentry->nota_msg, relname),
133 (wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
137 * Emit the right error message for a "DROP" command issued on a
138 * non-existent relation
141 DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
143 const struct msgstrings *rentry;
145 for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
147 if (rentry->kind == rightkind)
152 (errcode(rentry->nonexistent_code),
153 errmsg(rentry->nonexistent_msg, rel->relname)));
157 ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
163 Assert(rentry->kind != '\0'); /* Should be impossible */
167 * returns false if missing_ok is true and the object does not exist,
168 * true if object exists and permissions are OK,
174 CheckDropPermissions(RangeVar *rel, char rightkind, bool missing_ok)
178 Form_pg_class classform;
180 relOid = RangeVarGetRelid(rel, true);
181 if (!OidIsValid(relOid))
183 DropErrorMsgNonExistent(rel, rightkind, missing_ok);
187 tuple = SearchSysCache(RELOID,
188 ObjectIdGetDatum(relOid),
190 if (!HeapTupleIsValid(tuple))
191 elog(ERROR, "cache lookup failed for relation %u", relOid);
193 classform = (Form_pg_class) GETSTRUCT(tuple);
195 if (classform->relkind != rightkind)
196 DropErrorMsgWrongType(rel->relname, classform->relkind,
199 /* Allow DROP to either table owner or schema owner */
200 if (!pg_class_ownercheck(relOid, GetUserId()) &&
201 !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
202 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
205 if (!allowSystemTableMods && IsSystemClass(classform))
207 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
208 errmsg("permission denied: \"%s\" is a system catalog",
211 ReleaseSysCache(tuple);
217 * Verify user has ownership of specified relation, else ereport.
219 * If noCatalogs is true then we also deny access to system catalogs,
220 * except when allowSystemTableMods is true.
223 CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
228 relOid = RangeVarGetRelid(rel, false);
229 tuple = SearchSysCache(RELOID,
230 ObjectIdGetDatum(relOid),
232 if (!HeapTupleIsValid(tuple)) /* should not happen */
233 elog(ERROR, "cache lookup failed for relation %u", relOid);
235 if (!pg_class_ownercheck(relOid, GetUserId()))
236 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
241 if (!allowSystemTableMods &&
242 IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
244 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
245 errmsg("permission denied: \"%s\" is a system catalog",
249 ReleaseSysCache(tuple);
254 * QueryIsReadOnly: is an analyzed/rewritten query read-only?
256 * This is a much stricter test than we apply for XactReadOnly mode;
257 * the query must be *in truth* read-only, because the caller wishes
258 * not to do CommandCounterIncrement for it.
261 QueryIsReadOnly(Query *parsetree)
263 switch (parsetree->commandType)
266 if (parsetree->into != NULL)
267 return false; /* SELECT INTO */
268 else if (parsetree->rowMarks != NIL)
269 return false; /* SELECT FOR UPDATE/SHARE */
277 /* For now, treat all utility commands as read/write */
280 elog(WARNING, "unrecognized commandType: %d",
281 (int) parsetree->commandType);
288 * check_xact_readonly: is a utility command read-only?
290 * Here we use the loose rules of XactReadOnly mode: no permanent effects
291 * on the database are allowed.
294 check_xact_readonly(Node *parsetree)
300 * Note: Commands that need to do more complicated checking are handled
304 switch (nodeTag(parsetree))
306 case T_AlterDatabaseStmt:
307 case T_AlterDatabaseSetStmt:
308 case T_AlterDomainStmt:
309 case T_AlterFunctionStmt:
310 case T_AlterRoleStmt:
311 case T_AlterRoleSetStmt:
312 case T_AlterObjectSchemaStmt:
313 case T_AlterOwnerStmt:
315 case T_AlterTableStmt:
319 case T_CreateCastStmt:
320 case T_CreateConversionStmt:
322 case T_CreateDomainStmt:
323 case T_CreateFunctionStmt:
324 case T_CreateRoleStmt:
326 case T_CreatePLangStmt:
327 case T_CreateOpClassStmt:
329 case T_CreateSchemaStmt:
330 case T_CreateSeqStmt:
332 case T_CreateTableSpaceStmt:
333 case T_CreateTrigStmt:
334 case T_CompositeTypeStmt:
336 case T_RemoveAggrStmt:
340 case T_DropTableSpaceStmt:
341 case T_RemoveFuncStmt:
343 case T_DropPLangStmt:
344 case T_RemoveOperStmt:
345 case T_RemoveOpClassStmt:
346 case T_DropPropertyStmt:
348 case T_GrantRoleStmt:
350 case T_DropOwnedStmt:
351 case T_ReassignOwnedStmt:
353 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
354 errmsg("transaction is read-only")));
365 * general utility function invoker
367 * parsetree: the parse tree for the utility statement
368 * params: parameters to use during execution
369 * dest: where to send results
370 * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
371 * in which to store a command completion status string.
373 * completionTag is only set nonempty if we want to return a nondefault status.
375 * completionTag may be NULL if caller doesn't want a status string.
378 ProcessUtility(Node *parsetree,
379 ParamListInfo params,
383 check_xact_readonly(parsetree);
386 completionTag[0] = '\0';
388 switch (nodeTag(parsetree))
391 * ******************** transactions ********************
393 case T_TransactionStmt:
395 TransactionStmt *stmt = (TransactionStmt *) parsetree;
400 * START TRANSACTION, as defined by SQL99: Identical
401 * to BEGIN. Same code for both.
403 case TRANS_STMT_BEGIN:
404 case TRANS_STMT_START:
408 BeginTransactionBlock();
409 foreach(lc, stmt->options)
411 DefElem *item = (DefElem *) lfirst(lc);
413 if (strcmp(item->defname, "transaction_isolation") == 0)
414 SetPGVariable("transaction_isolation",
415 list_make1(item->arg),
417 else if (strcmp(item->defname, "transaction_read_only") == 0)
418 SetPGVariable("transaction_read_only",
419 list_make1(item->arg),
425 case TRANS_STMT_COMMIT:
426 if (!EndTransactionBlock())
428 /* report unsuccessful commit in completionTag */
430 strcpy(completionTag, "ROLLBACK");
434 case TRANS_STMT_PREPARE:
435 if (!PrepareTransactionBlock(stmt->gid))
437 /* report unsuccessful commit in completionTag */
439 strcpy(completionTag, "ROLLBACK");
443 case TRANS_STMT_COMMIT_PREPARED:
444 PreventTransactionChain(stmt, "COMMIT PREPARED");
445 FinishPreparedTransaction(stmt->gid, true);
448 case TRANS_STMT_ROLLBACK_PREPARED:
449 PreventTransactionChain(stmt, "ROLLBACK PREPARED");
450 FinishPreparedTransaction(stmt->gid, false);
453 case TRANS_STMT_ROLLBACK:
454 UserAbortTransactionBlock();
457 case TRANS_STMT_SAVEPOINT:
462 RequireTransactionChain((void *) stmt, "SAVEPOINT");
464 foreach(cell, stmt->options)
466 DefElem *elem = lfirst(cell);
468 if (strcmp(elem->defname, "savepoint_name") == 0)
469 name = strVal(elem->arg);
472 Assert(PointerIsValid(name));
474 DefineSavepoint(name);
478 case TRANS_STMT_RELEASE:
479 RequireTransactionChain((void *) stmt, "RELEASE SAVEPOINT");
480 ReleaseSavepoint(stmt->options);
483 case TRANS_STMT_ROLLBACK_TO:
484 RequireTransactionChain((void *) stmt, "ROLLBACK TO SAVEPOINT");
485 RollbackToSavepoint(stmt->options);
488 * CommitTransactionCommand is in charge of
489 * re-defining the savepoint again
497 * Portal (cursor) manipulation
499 case T_DeclareCursorStmt:
500 PerformCursorOpen((DeclareCursorStmt *) parsetree, params);
503 case T_ClosePortalStmt:
505 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
507 PerformPortalClose(stmt->portalname);
512 PerformPortalFetch((FetchStmt *) parsetree, dest,
517 * relation and attribute manipulation
519 case T_CreateSchemaStmt:
520 CreateSchemaCommand((CreateSchemaStmt *) parsetree);
527 relOid = DefineRelation((CreateStmt *) parsetree,
531 * Let AlterTableCreateToastTable decide if this one needs a
532 * secondary relation too.
534 CommandCounterIncrement();
535 AlterTableCreateToastTable(relOid, true);
539 case T_CreateTableSpaceStmt:
540 CreateTableSpace((CreateTableSpaceStmt *) parsetree);
543 case T_DropTableSpaceStmt:
544 DropTableSpace((DropTableSpaceStmt *) parsetree);
549 DropStmt *stmt = (DropStmt *) parsetree;
552 foreach(arg, stmt->objects)
554 List *names = (List *) lfirst(arg);
557 switch (stmt->removeType)
560 rel = makeRangeVarFromNameList(names);
561 if (CheckDropPermissions(rel, RELKIND_RELATION,
563 RemoveRelation(rel, stmt->behavior);
566 case OBJECT_SEQUENCE:
567 rel = makeRangeVarFromNameList(names);
568 if (CheckDropPermissions(rel, RELKIND_SEQUENCE,
570 RemoveRelation(rel, stmt->behavior);
574 rel = makeRangeVarFromNameList(names);
575 if (CheckDropPermissions(rel, RELKIND_VIEW,
577 RemoveView(rel, stmt->behavior);
581 rel = makeRangeVarFromNameList(names);
582 if (CheckDropPermissions(rel, RELKIND_INDEX,
584 RemoveIndex(rel, stmt->behavior);
588 /* RemoveType does its own permissions checks */
589 RemoveType(names, stmt->behavior,
596 * RemoveDomain does its own permissions checks
598 RemoveDomain(names, stmt->behavior,
602 case OBJECT_CONVERSION:
603 DropConversionCommand(names, stmt->behavior,
610 * RemoveSchema does its own permissions checks
612 RemoveSchema(names, stmt->behavior,
617 elog(ERROR, "unrecognized drop object type: %d",
618 (int) stmt->removeType);
623 * We used to need to do CommandCounterIncrement() here,
624 * but now it's done inside performDeletion().
632 TruncateStmt *stmt = (TruncateStmt *) parsetree;
634 ExecuteTruncate(stmt->relations);
639 CommentObject((CommentStmt *) parsetree);
643 DoCopy((CopyStmt *) parsetree);
647 PrepareQuery((PrepareStmt *) parsetree);
651 ExecuteQuery((ExecuteStmt *) parsetree, params,
652 dest, completionTag);
655 case T_DeallocateStmt:
656 DeallocateQuery((DeallocateStmt *) parsetree);
663 ExecRenameStmt((RenameStmt *) parsetree);
666 case T_AlterObjectSchemaStmt:
667 ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree);
670 case T_AlterOwnerStmt:
671 ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
674 case T_AlterTableStmt:
675 AlterTable((AlterTableStmt *) parsetree);
678 case T_AlterDomainStmt:
680 AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
683 * Some or all of these functions are recursive to cover
684 * inherited things, so permission checks are done there.
686 switch (stmt->subtype)
688 case 'T': /* ALTER DOMAIN DEFAULT */
691 * Recursively alter column default for table and, if
692 * requested, for descendants
694 AlterDomainDefault(stmt->typename,
697 case 'N': /* ALTER DOMAIN DROP NOT NULL */
698 AlterDomainNotNull(stmt->typename,
701 case 'O': /* ALTER DOMAIN SET NOT NULL */
702 AlterDomainNotNull(stmt->typename,
705 case 'C': /* ADD CONSTRAINT */
706 AlterDomainAddConstraint(stmt->typename,
709 case 'X': /* DROP CONSTRAINT */
710 AlterDomainDropConstraint(stmt->typename,
715 elog(ERROR, "unrecognized alter domain type: %d",
716 (int) stmt->subtype);
723 ExecuteGrantStmt((GrantStmt *) parsetree);
726 case T_GrantRoleStmt:
727 GrantRole((GrantRoleStmt *) parsetree);
731 * **************** object creation / destruction ******************
735 DefineStmt *stmt = (DefineStmt *) parsetree;
739 case OBJECT_AGGREGATE:
740 DefineAggregate(stmt->defnames, stmt->definition);
742 case OBJECT_OPERATOR:
743 DefineOperator(stmt->defnames, stmt->definition);
746 DefineType(stmt->defnames, stmt->definition);
749 elog(ERROR, "unrecognized define stmt type: %d",
756 case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
758 CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
760 DefineCompositeType(stmt->typevar, stmt->coldeflist);
764 case T_ViewStmt: /* CREATE VIEW */
766 ViewStmt *stmt = (ViewStmt *) parsetree;
768 DefineView(stmt->view, stmt->query, stmt->replace);
772 case T_CreateFunctionStmt: /* CREATE FUNCTION */
773 CreateFunction((CreateFunctionStmt *) parsetree);
776 case T_AlterFunctionStmt: /* ALTER FUNCTION */
777 AlterFunction((AlterFunctionStmt *) parsetree);
780 case T_IndexStmt: /* CREATE INDEX */
782 IndexStmt *stmt = (IndexStmt *) parsetree;
784 CheckRelationOwnership(stmt->relation, true);
786 DefineIndex(stmt->relation, /* relation */
787 stmt->idxname, /* index name */
788 InvalidOid, /* no predefined OID */
789 stmt->accessMethod, /* am name */
791 stmt->indexParams, /* parameters */
792 (Expr *) stmt->whereClause,
797 false, /* is_alter_table */
798 true, /* check_rights */
799 false, /* skip_build */
804 case T_RuleStmt: /* CREATE RULE */
805 DefineQueryRewrite((RuleStmt *) parsetree);
808 case T_CreateSeqStmt:
809 DefineSequence((CreateSeqStmt *) parsetree);
813 AlterSequence((AlterSeqStmt *) parsetree);
816 case T_RemoveAggrStmt:
817 RemoveAggregate((RemoveAggrStmt *) parsetree);
820 case T_RemoveFuncStmt:
821 RemoveFunction((RemoveFuncStmt *) parsetree);
824 case T_RemoveOperStmt:
825 RemoveOperator((RemoveOperStmt *) parsetree);
829 createdb((CreatedbStmt *) parsetree);
832 case T_AlterDatabaseStmt:
833 AlterDatabase((AlterDatabaseStmt *) parsetree);
836 case T_AlterDatabaseSetStmt:
837 AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
842 DropdbStmt *stmt = (DropdbStmt *) parsetree;
844 dropdb(stmt->dbname, stmt->missing_ok);
848 /* Query-level asynchronous notification */
851 NotifyStmt *stmt = (NotifyStmt *) parsetree;
853 Async_Notify(stmt->relation->relname);
859 ListenStmt *stmt = (ListenStmt *) parsetree;
861 Async_Listen(stmt->relation->relname);
867 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
869 Async_Unlisten(stmt->relation->relname);
875 LoadStmt *stmt = (LoadStmt *) parsetree;
879 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
880 errmsg("must be superuser to do LOAD")));
881 closeAllVfds(); /* probably not necessary... */
882 load_file(stmt->filename);
887 cluster((ClusterStmt *) parsetree);
891 vacuum((VacuumStmt *) parsetree, NIL);
895 ExplainQuery((ExplainStmt *) parsetree, params, dest);
898 case T_VariableSetStmt:
900 VariableSetStmt *n = (VariableSetStmt *) parsetree;
903 * Special cases for special SQL syntax that effectively sets
904 * more than one variable per statement.
906 if (strcmp(n->name, "TRANSACTION") == 0)
910 foreach(head, n->args)
912 DefElem *item = (DefElem *) lfirst(head);
914 if (strcmp(item->defname, "transaction_isolation") == 0)
915 SetPGVariable("transaction_isolation",
916 list_make1(item->arg), n->is_local);
917 else if (strcmp(item->defname, "transaction_read_only") == 0)
918 SetPGVariable("transaction_read_only",
919 list_make1(item->arg), n->is_local);
922 else if (strcmp(n->name, "SESSION CHARACTERISTICS") == 0)
926 foreach(head, n->args)
928 DefElem *item = (DefElem *) lfirst(head);
930 if (strcmp(item->defname, "transaction_isolation") == 0)
931 SetPGVariable("default_transaction_isolation",
932 list_make1(item->arg), n->is_local);
933 else if (strcmp(item->defname, "transaction_read_only") == 0)
934 SetPGVariable("default_transaction_read_only",
935 list_make1(item->arg), n->is_local);
939 SetPGVariable(n->name, n->args, n->is_local);
943 case T_VariableShowStmt:
945 VariableShowStmt *n = (VariableShowStmt *) parsetree;
947 GetPGVariable(n->name, dest);
951 case T_VariableResetStmt:
953 VariableResetStmt *n = (VariableResetStmt *) parsetree;
955 ResetPGVariable(n->name);
959 case T_CreateTrigStmt:
960 CreateTrigger((CreateTrigStmt *) parsetree, false);
963 case T_DropPropertyStmt:
965 DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
968 relId = RangeVarGetRelid(stmt->relation, false);
970 switch (stmt->removeType)
973 /* RemoveRewriteRule checks permissions */
974 RemoveRewriteRule(relId, stmt->property,
978 /* DropTrigger checks permissions */
979 DropTrigger(relId, stmt->property,
983 elog(ERROR, "unrecognized object type: %d",
984 (int) stmt->removeType);
990 case T_CreatePLangStmt:
991 CreateProceduralLanguage((CreatePLangStmt *) parsetree);
994 case T_DropPLangStmt:
995 DropProceduralLanguage((DropPLangStmt *) parsetree);
999 * ******************************** DOMAIN statements ****
1001 case T_CreateDomainStmt:
1002 DefineDomain((CreateDomainStmt *) parsetree);
1006 * ******************************** ROLE statements ****
1008 case T_CreateRoleStmt:
1009 CreateRole((CreateRoleStmt *) parsetree);
1012 case T_AlterRoleStmt:
1013 AlterRole((AlterRoleStmt *) parsetree);
1016 case T_AlterRoleSetStmt:
1017 AlterRoleSet((AlterRoleSetStmt *) parsetree);
1020 case T_DropRoleStmt:
1021 DropRole((DropRoleStmt *) parsetree);
1024 case T_DropOwnedStmt:
1025 DropOwnedObjects((DropOwnedStmt *) parsetree);
1028 case T_ReassignOwnedStmt:
1029 ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
1033 LockTableCommand((LockStmt *) parsetree);
1036 case T_ConstraintsSetStmt:
1037 AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
1040 case T_CheckPointStmt:
1043 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1044 errmsg("must be superuser to do CHECKPOINT")));
1045 RequestCheckpoint(true, false);
1050 ReindexStmt *stmt = (ReindexStmt *) parsetree;
1055 ReindexIndex(stmt->relation);
1058 ReindexTable(stmt->relation);
1060 case OBJECT_DATABASE:
1061 ReindexDatabase(stmt->name,
1062 stmt->do_system, stmt->do_user);
1065 elog(ERROR, "unrecognized object type: %d",
1073 case T_CreateConversionStmt:
1074 CreateConversionCommand((CreateConversionStmt *) parsetree);
1077 case T_CreateCastStmt:
1078 CreateCast((CreateCastStmt *) parsetree);
1081 case T_DropCastStmt:
1082 DropCast((DropCastStmt *) parsetree);
1085 case T_CreateOpClassStmt:
1086 DefineOpClass((CreateOpClassStmt *) parsetree);
1089 case T_RemoveOpClassStmt:
1090 RemoveOpClass((RemoveOpClassStmt *) parsetree);
1094 elog(ERROR, "unrecognized node type: %d",
1095 (int) nodeTag(parsetree));
1101 * UtilityReturnsTuples
1102 * Return "true" if this utility statement will send output to the
1105 * Generally, there should be a case here for each case in ProcessUtility
1106 * where "dest" is passed on.
1109 UtilityReturnsTuples(Node *parsetree)
1111 switch (nodeTag(parsetree))
1115 FetchStmt *stmt = (FetchStmt *) parsetree;
1120 portal = GetPortalByName(stmt->portalname);
1121 if (!PortalIsValid(portal))
1122 return false; /* not our business to raise error */
1123 return portal->tupDesc ? true : false;
1128 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
1129 PreparedStatement *entry;
1133 entry = FetchPreparedStatement(stmt->name, false);
1135 return false; /* not our business to raise error */
1136 switch (ChoosePortalStrategy(entry->query_list))
1138 case PORTAL_ONE_SELECT:
1140 case PORTAL_UTIL_SELECT:
1142 case PORTAL_MULTI_QUERY:
1143 /* will not return tuples */
1152 case T_VariableShowStmt:
1161 * UtilityTupleDescriptor
1162 * Fetch the actual output tuple descriptor for a utility statement
1163 * for which UtilityReturnsTuples() previously returned "true".
1165 * The returned descriptor is created in (or copied into) the current memory
1169 UtilityTupleDescriptor(Node *parsetree)
1171 switch (nodeTag(parsetree))
1175 FetchStmt *stmt = (FetchStmt *) parsetree;
1180 portal = GetPortalByName(stmt->portalname);
1181 if (!PortalIsValid(portal))
1182 return NULL; /* not our business to raise error */
1183 return CreateTupleDescCopy(portal->tupDesc);
1188 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
1189 PreparedStatement *entry;
1193 entry = FetchPreparedStatement(stmt->name, false);
1195 return NULL; /* not our business to raise error */
1196 return FetchPreparedStatementResultDesc(entry);
1200 return ExplainResultDesc((ExplainStmt *) parsetree);
1202 case T_VariableShowStmt:
1204 VariableShowStmt *n = (VariableShowStmt *) parsetree;
1206 return GetPGVariableResultDesc(n->name);
1217 * utility to get a string representation of the
1218 * command operation, given a raw (un-analyzed) parsetree.
1220 * This must handle all raw command types, but since the vast majority
1221 * of 'em are utility commands, it seems sensible to keep it here.
1223 * NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
1224 * Also, the result must point at a true constant (permanent storage).
1227 CreateCommandTag(Node *parsetree)
1231 switch (nodeTag(parsetree))
1249 case T_TransactionStmt:
1251 TransactionStmt *stmt = (TransactionStmt *) parsetree;
1255 case TRANS_STMT_BEGIN:
1259 case TRANS_STMT_START:
1260 tag = "START TRANSACTION";
1263 case TRANS_STMT_COMMIT:
1267 case TRANS_STMT_ROLLBACK:
1268 case TRANS_STMT_ROLLBACK_TO:
1272 case TRANS_STMT_SAVEPOINT:
1276 case TRANS_STMT_RELEASE:
1280 case TRANS_STMT_PREPARE:
1281 tag = "PREPARE TRANSACTION";
1284 case TRANS_STMT_COMMIT_PREPARED:
1285 tag = "COMMIT PREPARED";
1288 case TRANS_STMT_ROLLBACK_PREPARED:
1289 tag = "ROLLBACK PREPARED";
1299 case T_DeclareCursorStmt:
1300 tag = "DECLARE CURSOR";
1303 case T_ClosePortalStmt:
1304 tag = "CLOSE CURSOR";
1309 FetchStmt *stmt = (FetchStmt *) parsetree;
1311 tag = (stmt->ismove) ? "MOVE" : "FETCH";
1315 case T_CreateDomainStmt:
1316 tag = "CREATE DOMAIN";
1319 case T_CreateSchemaStmt:
1320 tag = "CREATE SCHEMA";
1324 tag = "CREATE TABLE";
1327 case T_CreateTableSpaceStmt:
1328 tag = "CREATE TABLESPACE";
1331 case T_DropTableSpaceStmt:
1332 tag = "DROP TABLESPACE";
1336 switch (((DropStmt *) parsetree)->removeType)
1341 case OBJECT_SEQUENCE:
1342 tag = "DROP SEQUENCE";
1354 tag = "DROP DOMAIN";
1356 case OBJECT_CONVERSION:
1357 tag = "DROP CONVERSION";
1360 tag = "DROP SCHEMA";
1367 case T_TruncateStmt:
1368 tag = "TRUNCATE TABLE";
1380 switch (((RenameStmt *) parsetree)->renameType)
1382 case OBJECT_AGGREGATE:
1383 tag = "ALTER AGGREGATE";
1385 case OBJECT_CONVERSION:
1386 tag = "ALTER CONVERSION";
1388 case OBJECT_DATABASE:
1389 tag = "ALTER DATABASE";
1391 case OBJECT_FUNCTION:
1392 tag = "ALTER FUNCTION";
1395 tag = "ALTER INDEX";
1397 case OBJECT_LANGUAGE:
1398 tag = "ALTER LANGUAGE";
1400 case OBJECT_OPCLASS:
1401 tag = "ALTER OPERATOR CLASS";
1407 tag = "ALTER SCHEMA";
1411 tag = "ALTER TABLE";
1413 case OBJECT_TABLESPACE:
1414 tag = "ALTER TABLESPACE";
1416 case OBJECT_TRIGGER:
1417 tag = "ALTER TRIGGER";
1425 case T_AlterObjectSchemaStmt:
1426 switch (((AlterObjectSchemaStmt *) parsetree)->objectType)
1428 case OBJECT_AGGREGATE:
1429 tag = "ALTER AGGREGATE";
1432 tag = "ALTER DOMAIN";
1434 case OBJECT_FUNCTION:
1435 tag = "ALTER FUNCTION";
1437 case OBJECT_SEQUENCE:
1438 tag = "ALTER SEQUENCE";
1441 tag = "ALTER TABLE";
1452 case T_AlterOwnerStmt:
1453 switch (((AlterOwnerStmt *) parsetree)->objectType)
1455 case OBJECT_AGGREGATE:
1456 tag = "ALTER AGGREGATE";
1458 case OBJECT_CONVERSION:
1459 tag = "ALTER CONVERSION";
1461 case OBJECT_DATABASE:
1462 tag = "ALTER DATABASE";
1465 tag = "ALTER DOMAIN";
1467 case OBJECT_FUNCTION:
1468 tag = "ALTER FUNCTION";
1470 case OBJECT_OPERATOR:
1471 tag = "ALTER OPERATOR";
1473 case OBJECT_OPCLASS:
1474 tag = "ALTER OPERATOR CLASS";
1477 tag = "ALTER SCHEMA";
1479 case OBJECT_TABLESPACE:
1480 tag = "ALTER TABLESPACE";
1491 case T_AlterTableStmt:
1493 AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
1496 * We might be supporting ALTER INDEX here, so set the
1497 * completion table appropriately. Catch all other
1498 * possibilities with ALTER TABLE
1501 if (stmt->relkind == OBJECT_INDEX)
1502 tag = "ALTER INDEX";
1504 tag = "ALTER TABLE";
1508 case T_AlterDomainStmt:
1509 tag = "ALTER DOMAIN";
1512 case T_AlterFunctionStmt:
1513 tag = "ALTER FUNCTION";
1518 GrantStmt *stmt = (GrantStmt *) parsetree;
1520 tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
1524 case T_GrantRoleStmt:
1526 GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
1528 tag = (stmt->is_grant) ? "GRANT ROLE" : "REVOKE ROLE";
1533 switch (((DefineStmt *) parsetree)->kind)
1535 case OBJECT_AGGREGATE:
1536 tag = "CREATE AGGREGATE";
1538 case OBJECT_OPERATOR:
1539 tag = "CREATE OPERATOR";
1542 tag = "CREATE TYPE";
1549 case T_CompositeTypeStmt:
1550 tag = "CREATE TYPE";
1554 tag = "CREATE VIEW";
1557 case T_CreateFunctionStmt:
1558 tag = "CREATE FUNCTION";
1562 tag = "CREATE INDEX";
1566 tag = "CREATE RULE";
1569 case T_CreateSeqStmt:
1570 tag = "CREATE SEQUENCE";
1573 case T_AlterSeqStmt:
1574 tag = "ALTER SEQUENCE";
1577 case T_RemoveAggrStmt:
1578 tag = "DROP AGGREGATE";
1581 case T_RemoveFuncStmt:
1582 tag = "DROP FUNCTION";
1585 case T_RemoveOperStmt:
1586 tag = "DROP OPERATOR";
1589 case T_CreatedbStmt:
1590 tag = "CREATE DATABASE";
1593 case T_AlterDatabaseStmt:
1594 tag = "ALTER DATABASE";
1597 case T_AlterDatabaseSetStmt:
1598 tag = "ALTER DATABASE";
1602 tag = "DROP DATABASE";
1613 case T_UnlistenStmt:
1626 if (((VacuumStmt *) parsetree)->vacuum)
1636 case T_VariableSetStmt:
1640 case T_VariableShowStmt:
1644 case T_VariableResetStmt:
1648 case T_CreateTrigStmt:
1649 tag = "CREATE TRIGGER";
1652 case T_DropPropertyStmt:
1653 switch (((DropPropertyStmt *) parsetree)->removeType)
1655 case OBJECT_TRIGGER:
1656 tag = "DROP TRIGGER";
1666 case T_CreatePLangStmt:
1667 tag = "CREATE LANGUAGE";
1670 case T_DropPLangStmt:
1671 tag = "DROP LANGUAGE";
1674 case T_CreateRoleStmt:
1675 tag = "CREATE ROLE";
1678 case T_AlterRoleStmt:
1682 case T_AlterRoleSetStmt:
1686 case T_DropRoleStmt:
1690 case T_DropOwnedStmt:
1694 case T_ReassignOwnedStmt:
1695 tag = "REASSIGN OWNED";
1702 case T_ConstraintsSetStmt:
1703 tag = "SET CONSTRAINTS";
1706 case T_CheckPointStmt:
1714 case T_CreateConversionStmt:
1715 tag = "CREATE CONVERSION";
1718 case T_CreateCastStmt:
1719 tag = "CREATE CAST";
1722 case T_DropCastStmt:
1726 case T_CreateOpClassStmt:
1727 tag = "CREATE OPERATOR CLASS";
1730 case T_RemoveOpClassStmt:
1731 tag = "DROP OPERATOR CLASS";
1742 case T_DeallocateStmt:
1747 elog(WARNING, "unrecognized node type: %d",
1748 (int) nodeTag(parsetree));
1758 * utility to get a string representation of a Query operation.
1760 * This is exactly like CreateCommandTag, except it works on a Query
1761 * that has already been through parse analysis (and possibly further).
1764 CreateQueryTag(Query *parsetree)
1768 switch (parsetree->commandType)
1773 * We take a little extra care here so that the result will be
1774 * useful for complaints about read-only statements
1776 if (parsetree->into != NULL)
1777 tag = "SELECT INTO";
1778 else if (parsetree->rowMarks != NIL)
1780 if (parsetree->forUpdate)
1781 tag = "SELECT FOR UPDATE";
1783 tag = "SELECT FOR SHARE";
1798 tag = CreateCommandTag(parsetree->utilityStmt);
1801 elog(WARNING, "unrecognized commandType: %d",
1802 (int) parsetree->commandType);