postgresql/src/backend/tcop/utility.c

1025 lines
24 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* utility.c
* Contains functions which control the execution of the POSTGRES utility
* commands. At one time acted as an interface between the Lisp and C
* systems.
*
2002-06-20 22:29:54 +02:00
* Portions Copyright (c) 1996-2002, 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.193 2003/02/19 03:59:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
1999-07-16 07:00:38 +02:00
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
2001-01-27 11:19:52 +01:00
#include "catalog/pg_shadow.h"
#include "commands/async.h"
#include "commands/cluster.h"
#include "commands/comment.h"
#include "commands/copy.h"
#include "commands/conversioncmds.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/explain.h"
#include "commands/lockcmds.h"
#include "commands/portalcmds.h"
#include "commands/prepare.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
1999-07-16 07:00:38 +02:00
#include "commands/sequence.h"
#include "commands/tablecmds.h"
1999-07-16 07:00:38 +02:00
#include "commands/trigger.h"
2002-12-06 06:00:34 +01:00
#include "commands/typecmds.h"
#include "commands/user.h"
1999-07-16 07:00:38 +02:00
#include "commands/vacuum.h"
#include "commands/view.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_clause.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
#include "rewrite/rewriteDefine.h"
1999-07-16 07:00:38 +02:00
#include "rewrite/rewriteRemove.h"
1996-11-11 05:54:54 +01:00
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "access/xlog.h"
/*
* Error-checking support for DROP commands
*/
2001-03-22 05:01:46 +01:00
struct kindstrings
{
char kind;
char *indef_article;
char *name;
char *command;
};
static struct kindstrings kindstringarray[] = {
2001-03-22 05:01:46 +01:00
{RELKIND_RELATION, "a", "table", "TABLE"},
{RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
{RELKIND_VIEW, "a", "view", "VIEW"},
{RELKIND_INDEX, "an", "index", "INDEX"},
{RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"},
2001-03-22 05:01:46 +01:00
{'\0', "a", "???", "???"}
};
static void
2001-03-22 05:01:46 +01:00
DropErrorMsg(char *relname, char wrongkind, char rightkind)
{
struct kindstrings *rentry;
struct kindstrings *wentry;
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);
/* Allow DROP to either table owner or schema owner */
if (!pg_class_ownercheck(relOid, GetUserId()) &&
!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
if (!allowSystemTableMods && IsSystemClass(classform))
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()))
aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
if (noCatalogs)
{
if (!allowSystemTableMods &&
IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
elog(ERROR, "relation \"%s\" is a system catalog",
rel->relname);
}
ReleaseSysCache(tuple);
}
static void
check_xact_readonly(Node *parsetree)
{
if (!XactReadOnly)
return;
/*
* Note: Commands that need to do more complicated checking are
* handled elsewhere.
*/
switch (nodeTag(parsetree))
{
case T_AlterDatabaseSetStmt:
case T_AlterDomainStmt:
case T_AlterGroupStmt:
case T_AlterTableStmt:
case T_RenameStmt:
case T_AlterUserStmt:
case T_AlterUserSetStmt:
case T_CommentStmt:
case T_DefineStmt:
case T_CreateCastStmt:
case T_CreateConversionStmt:
case T_CreatedbStmt:
case T_CreateDomainStmt:
case T_CreateFunctionStmt:
case T_CreateGroupStmt:
case T_IndexStmt:
case T_CreatePLangStmt:
case T_CreateOpClassStmt:
case T_RuleStmt:
case T_CreateSchemaStmt:
case T_CreateSeqStmt:
case T_CreateStmt:
case T_CreateTrigStmt:
case T_CompositeTypeStmt:
case T_CreateUserStmt:
case T_ViewStmt:
case T_RemoveAggrStmt:
case T_DropCastStmt:
case T_DropStmt:
case T_DropdbStmt:
case T_RemoveFuncStmt:
case T_DropGroupStmt:
case T_DropPLangStmt:
case T_RemoveOperStmt:
case T_RemoveOpClassStmt:
case T_DropPropertyStmt:
case T_DropUserStmt:
case T_GrantStmt:
case T_TruncateStmt:
elog(ERROR, "transaction is read-only");
break;
default:
/*nothing*/;
}
}
/*
* 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,
char *completionTag)
{
check_xact_readonly(parsetree);
if (completionTag)
completionTag[0] = '\0';
switch (nodeTag(parsetree))
{
/*
* ******************** transactions ********************
*/
case T_TransactionStmt:
{
TransactionStmt *stmt = (TransactionStmt *) parsetree;
switch (stmt->kind)
{
case TRANS_STMT_BEGIN:
BeginTransactionBlock();
break;
2002-09-04 22:31:48 +02:00
/*
* START TRANSACTION, as defined by SQL99:
* Identical to BEGIN, except that it takes a few
* additional options.
*/
case TRANS_STMT_START:
{
BeginTransactionBlock();
if (stmt->options)
{
List *head;
foreach(head, stmt->options)
{
DefElem *item = (DefElem *) lfirst(head);
if (strcmp(item->defname, "transaction_isolation")==0)
SetPGVariable("transaction_isolation",
makeList1(item->arg), false);
else if (strcmp(item->defname, "transaction_read_only")==0)
SetPGVariable("transaction_read_only",
makeList1(item->arg), false);
}
}
}
break;
case TRANS_STMT_COMMIT:
EndTransactionBlock();
break;
case TRANS_STMT_ROLLBACK:
UserAbortTransactionBlock();
break;
}
}
break;
/*
* ************************* portal manipulation ***************************
*/
case T_ClosePortalStmt:
{
ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
PerformPortalClose(stmt->portalname, dest);
}
break;
case T_FetchStmt:
{
FetchStmt *stmt = (FetchStmt *) parsetree;
PerformPortalFetch(stmt->portalname,
stmt->direction == FETCH_FORWARD,
stmt->howMany,
(stmt->ismove) ? None : dest,
completionTag);
}
break;
/*
* relation and attribute manipulation
*/
case T_CreateSchemaStmt:
CreateSchemaCommand((CreateSchemaStmt *) parsetree);
break;
case T_CreateStmt:
{
Oid relOid;
relOid = DefineRelation((CreateStmt *) parsetree,
RELKIND_RELATION);
/*
2002-09-04 22:31:48 +02:00
* Let AlterTableCreateToastTable decide if this one needs
* a secondary relation too.
*/
CommandCounterIncrement();
AlterTableCreateToastTable(relOid, true);
}
break;
case T_DropStmt:
{
DropStmt *stmt = (DropStmt *) parsetree;
List *arg;
foreach(arg, stmt->objects)
{
2002-09-04 22:31:48 +02:00
List *names = (List *) lfirst(arg);
RangeVar *rel;
2001-03-22 05:01:46 +01:00
switch (stmt->removeType)
{
case DROP_TABLE:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_RELATION);
RemoveRelation(rel, stmt->behavior);
break;
case DROP_SEQUENCE:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_SEQUENCE);
RemoveRelation(rel, stmt->behavior);
break;
case DROP_VIEW:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_VIEW);
RemoveView(rel, stmt->behavior);
break;
case DROP_INDEX:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_INDEX);
RemoveIndex(rel, stmt->behavior);
break;
2002-03-20 20:45:13 +01:00
case DROP_TYPE:
/* RemoveType does its own permissions checks */
RemoveType(names, stmt->behavior);
break;
2002-03-20 20:45:13 +01:00
case DROP_DOMAIN:
2002-09-04 22:31:48 +02:00
/*
* RemoveDomain does its own permissions
* checks
*/
RemoveDomain(names, stmt->behavior);
break;
case DROP_CONVERSION:
DropConversionCommand(names, stmt->behavior);
break;
case DROP_SCHEMA:
2002-09-04 22:31:48 +02:00
/*
* RemoveSchema does its own permissions
* checks
*/
RemoveSchema(names, stmt->behavior);
break;
}
/*
* We used to need to do CommandCounterIncrement()
* here, but now it's done inside performDeletion().
*/
}
}
break;
case T_TruncateStmt:
{
2002-09-04 22:31:48 +02:00
TruncateStmt *stmt = (TruncateStmt *) parsetree;
TruncateRelation(stmt->relation);
}
break;
case T_CommentStmt:
CommentObject((CommentStmt *) parsetree);
break;
case T_CopyStmt:
DoCopy((CopyStmt *) parsetree);
break;
case T_PrepareStmt:
PrepareQuery((PrepareStmt *) parsetree);
break;
case T_ExecuteStmt:
ExecuteQuery((ExecuteStmt *) parsetree, dest);
break;
case T_DeallocateStmt:
DeallocateQuery((DeallocateStmt *) parsetree);
break;
/*
* schema
*/
case T_RenameStmt:
{
RenameStmt *stmt = (RenameStmt *) parsetree;
2002-09-04 22:31:48 +02:00
Oid relid;
CheckOwnership(stmt->relation, true);
relid = RangeVarGetRelid(stmt->relation, false);
switch (stmt->renameType)
{
case RENAME_TABLE:
2002-09-04 22:31:48 +02:00
{
/*
* RENAME TABLE requires that we (still) hold
* CREATE rights on the containing namespace,
* as well as ownership of the table.
*/
Oid namespaceId = get_rel_namespace(relid);
AclResult aclresult;
2002-09-04 22:31:48 +02:00
aclresult = pg_namespace_aclcheck(namespaceId,
GetUserId(),
ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult,
get_namespace_name(namespaceId));
2002-09-04 22:31:48 +02:00
renamerel(relid, stmt->newname);
break;
}
case RENAME_COLUMN:
renameatt(relid,
2002-09-04 22:31:48 +02:00
stmt->oldname, /* old att name */
stmt->newname, /* new att name */
interpretInhOption(stmt->relation->inhOpt), /* recursive? */
false); /* recursing already? */
break;
case RENAME_TRIGGER:
renametrig(relid,
2002-09-04 22:31:48 +02:00
stmt->oldname, /* old att name */
stmt->newname); /* new att name */
break;
case RENAME_RULE:
2003-01-06 01:31:45 +01:00
elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d",
2002-09-04 22:31:48 +02:00
stmt->renameType);
break;
default:
2003-01-06 01:31:45 +01:00
elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d",
2002-09-04 22:31:48 +02:00
stmt->renameType);
}
}
break;
/* various Alter Table forms */
case T_AlterTableStmt:
{
AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
2002-09-04 22:31:48 +02:00
Oid relid;
relid = RangeVarGetRelid(stmt->relation, false);
/*
* Some or all of these functions are recursive to cover
* inherited things, so permission checks are done there.
*/
switch (stmt->subtype)
{
case 'A': /* ADD COLUMN */
2002-09-04 22:31:48 +02:00
/*
2002-09-04 22:31:48 +02:00
* Recursively add column to table and, if
* requested, to descendants
*/
AlterTableAddColumn(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
(ColumnDef *) stmt->def);
break;
case 'T': /* ALTER COLUMN DEFAULT */
2002-09-04 22:31:48 +02:00
2002-04-12 11:17:10 +02:00
/*
* Recursively alter column default for table and,
* if requested, for descendants
*/
AlterTableAlterColumnDefault(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->def);
break;
case 'N': /* ALTER COLUMN DROP NOT NULL */
AlterTableAlterColumnDropNotNull(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
stmt->name);
break;
case 'n': /* ALTER COLUMN SET NOT NULL */
AlterTableAlterColumnSetNotNull(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
stmt->name);
break;
case 'S': /* ALTER COLUMN STATISTICS */
2002-09-04 22:31:48 +02:00
case 'M': /* ALTER COLUMN STORAGE */
/*
2002-09-04 22:31:48 +02:00
* Recursively alter column statistics for table
* and, if requested, for descendants
*/
AlterTableAlterColumnFlags(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->def,
&(stmt->subtype));
break;
case 'D': /* DROP COLUMN */
2002-09-04 22:31:48 +02:00
/*
* Recursively drop column from table and, if
* requested, from descendants
*/
AlterTableDropColumn(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
false,
stmt->name,
stmt->behavior);
break;
case 'C': /* ADD CONSTRAINT */
2002-09-04 22:31:48 +02:00
/*
2002-09-04 22:31:48 +02:00
* Recursively add constraint to table and, if
* requested, to descendants
*/
AlterTableAddConstraint(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
(List *) stmt->def);
break;
case 'X': /* DROP CONSTRAINT */
2002-09-04 22:31:48 +02:00
2002-04-12 11:17:10 +02:00
/*
2002-09-04 22:31:48 +02:00
* Recursively drop constraint from table and, if
* requested, from descendants
*/
AlterTableDropConstraint(relid,
2002-09-04 22:31:48 +02:00
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->behavior);
break;
case 'E': /* CREATE TOAST TABLE */
AlterTableCreateToastTable(relid, false);
break;
case 'U': /* ALTER OWNER */
/* check that we are the superuser */
if (!superuser())
elog(ERROR, "ALTER TABLE: permission denied");
/* get_usesysid raises an error if no such user */
AlterTableOwner(relid,
get_usesysid(stmt->name));
break;
case 'o': /* ADD OIDS */
AlterTableAlterOids(relid,
interpretInhOption(stmt->relation->inhOpt),
false);
break;
default: /* oops */
2003-01-06 01:31:45 +01:00
elog(ERROR, "ProcessUtility: Invalid type for AlterTableStmt: %d",
stmt->subtype);
break;
}
}
break;
2002-12-06 06:00:34 +01:00
case T_AlterDomainStmt:
{
AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
/*
* Some or all of these functions are recursive to cover
* inherited things, so permission checks are done there.
*/
switch (stmt->subtype)
{
case 'T': /* ALTER COLUMN DEFAULT */
/*
* Recursively alter column default for table and,
* if requested, for descendants
*/
AlterDomainDefault(stmt->typename,
stmt->def);
break;
case 'N': /* ALTER COLUMN DROP NOT NULL */
AlterDomainNotNull(stmt->typename,
false);
break;
case 'O': /* ALTER COLUMN SET NOT NULL */
AlterDomainNotNull(stmt->typename,
true);
break;
case 'C': /* ADD CONSTRAINT */
AlterDomainAddConstraint(stmt->typename,
stmt->def);
break;
case 'X': /* DROP CONSTRAINT */
AlterDomainDropConstraint(stmt->typename,
stmt->name,
stmt->behavior);
break;
2003-01-06 01:31:45 +01:00
case 'U': /* OWNER TO */
/* check that we are the superuser */
if (!superuser())
elog(ERROR, "ALTER DOMAIN: permission denied");
/* get_usesysid raises an error if no such user */
AlterTypeOwner(stmt->typename,
get_usesysid(stmt->name));
break;
2002-12-06 06:00:34 +01:00
default: /* oops */
2003-01-06 01:31:45 +01:00
elog(ERROR, "ProcessUtility: Invalid type for AlterDomainStmt: %d",
stmt->subtype);
2002-12-06 06:00:34 +01:00
break;
}
}
break;
case T_GrantStmt:
ExecuteGrantStmt((GrantStmt *) parsetree);
break;
/*
* ******************************** object creation /
* destruction ********************************
*
*/
case T_DefineStmt:
{
DefineStmt *stmt = (DefineStmt *) parsetree;
switch (stmt->kind)
{
case DEFINE_STMT_AGGREGATE:
DefineAggregate(stmt->defnames, stmt->definition);
break;
case DEFINE_STMT_OPERATOR:
DefineOperator(stmt->defnames, stmt->definition);
break;
case DEFINE_STMT_TYPE:
DefineType(stmt->defnames, stmt->definition);
break;
}
}
break;
case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
{
2002-09-04 22:31:48 +02:00
CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
DefineCompositeType(stmt->typevar, stmt->coldeflist);
}
break;
case T_ViewStmt: /* CREATE VIEW */
{
ViewStmt *stmt = (ViewStmt *) parsetree;
DefineView(stmt->view, stmt->query, stmt->replace);
}
break;
2002-09-04 22:31:48 +02:00
case T_CreateFunctionStmt: /* CREATE FUNCTION */
CreateFunction((CreateFunctionStmt *) parsetree);
break;
case T_IndexStmt: /* CREATE INDEX */
{
IndexStmt *stmt = (IndexStmt *) parsetree;
CheckOwnership(stmt->relation, true);
2002-09-04 22:31:48 +02:00
DefineIndex(stmt->relation, /* relation */
stmt->idxname, /* index name */
stmt->accessMethod, /* am name */
stmt->indexParams, /* parameters */
stmt->unique,
stmt->primary,
stmt->isconstraint,
(Expr *) stmt->whereClause,
stmt->rangetable);
}
break;
case T_RuleStmt: /* CREATE RULE */
DefineQueryRewrite((RuleStmt *) parsetree);
break;
case T_CreateSeqStmt:
DefineSequence((CreateSeqStmt *) parsetree);
break;
case T_RemoveAggrStmt:
RemoveAggregate((RemoveAggrStmt *) parsetree);
break;
case T_RemoveFuncStmt:
RemoveFunction((RemoveFuncStmt *) parsetree);
break;
case T_RemoveOperStmt:
RemoveOperator((RemoveOperStmt *) parsetree);
break;
case T_CreatedbStmt:
createdb((CreatedbStmt *) parsetree);
break;
case T_AlterDatabaseSetStmt:
AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
break;
case T_DropdbStmt:
{
DropdbStmt *stmt = (DropdbStmt *) parsetree;
dropdb(stmt->dbname);
}
break;
/* Query-level asynchronous notification */
case T_NotifyStmt:
{
NotifyStmt *stmt = (NotifyStmt *) parsetree;
Async_Notify(stmt->relation->relname);
}
break;
case T_ListenStmt:
{
ListenStmt *stmt = (ListenStmt *) parsetree;
Async_Listen(stmt->relation->relname, MyProcPid);
}
break;
case T_UnlistenStmt:
{
UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
Async_Unlisten(stmt->relation->relname, MyProcPid);
}
break;
case T_LoadStmt:
{
LoadStmt *stmt = (LoadStmt *) parsetree;
1999-05-25 18:15:34 +02:00
closeAllVfds(); /* probably not necessary... */
load_file(stmt->filename);
}
break;
case T_ClusterStmt:
cluster((ClusterStmt *) parsetree);
break;
case T_VacuumStmt:
vacuum((VacuumStmt *) parsetree);
break;
case T_ExplainStmt:
ExplainQuery((ExplainStmt *) parsetree, dest);
break;
case T_VariableSetStmt:
{
VariableSetStmt *n = (VariableSetStmt *) parsetree;
/*
* Special cases for special SQL syntax that
* effectively sets more than one variable per
* statement.
*/
if (strcmp(n->name, "TRANSACTION")==0)
{
List *head;
foreach(head, n->args)
{
DefElem *item = (DefElem *) lfirst(head);
if (strcmp(item->defname, "transaction_isolation")==0)
SetPGVariable("transaction_isolation",
makeList1(item->arg), n->is_local);
else if (strcmp(item->defname, "transaction_read_only")==0)
SetPGVariable("transaction_read_only",
makeList1(item->arg), n->is_local);
}
}
else if (strcmp(n->name, "SESSION CHARACTERISTICS")==0)
{
List *head;
foreach(head, n->args)
{
DefElem *item = (DefElem *) lfirst(head);
if (strcmp(item->defname, "transaction_isolation")==0)
SetPGVariable("default_transaction_isolation",
makeList1(item->arg), n->is_local);
else if (strcmp(item->defname, "transaction_read_only")==0)
SetPGVariable("default_transaction_read_only",
makeList1(item->arg), n->is_local);
}
}
else
SetPGVariable(n->name, n->args, n->is_local);
}
break;
case T_VariableShowStmt:
{
VariableShowStmt *n = (VariableShowStmt *) parsetree;
GetPGVariable(n->name);
}
break;
case T_VariableResetStmt:
{
VariableResetStmt *n = (VariableResetStmt *) parsetree;
ResetPGVariable(n->name);
}
break;
case T_CreateTrigStmt:
CreateTrigger((CreateTrigStmt *) parsetree, false);
break;
case T_DropPropertyStmt:
{
DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
2002-09-04 22:31:48 +02:00
Oid relId;
relId = RangeVarGetRelid(stmt->relation, false);
switch (stmt->removeType)
{
case DROP_RULE:
/* RemoveRewriteRule checks permissions */
RemoveRewriteRule(relId, stmt->property,
stmt->behavior);
break;
case DROP_TRIGGER:
/* DropTrigger checks permissions */
DropTrigger(relId, stmt->property,
stmt->behavior);
break;
}
}
break;
case T_CreatePLangStmt:
CreateProceduralLanguage((CreatePLangStmt *) parsetree);
break;
case T_DropPLangStmt:
DropProceduralLanguage((DropPLangStmt *) parsetree);
break;
/*
* ******************************** DOMAIN statements ****
*/
case T_CreateDomainStmt:
DefineDomain((CreateDomainStmt *) parsetree);
break;
/*
* ******************************** USER statements ****
*/
case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree);
break;
case T_AlterUserStmt:
AlterUser((AlterUserStmt *) parsetree);
break;
case T_AlterUserSetStmt:
AlterUserSet((AlterUserSetStmt *) parsetree);
break;
case T_DropUserStmt:
DropUser((DropUserStmt *) parsetree);
break;
case T_LockStmt:
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, "CHECKPOINT: permission denied");
CreateCheckPoint(false, false);
break;
2000-02-18 10:30:20 +01:00
case T_ReindexStmt:
{
ReindexStmt *stmt = (ReindexStmt *) parsetree;
switch (stmt->kind)
2000-02-18 10:30:20 +01:00
{
case REINDEX_INDEX:
CheckOwnership(stmt->relation, false);
ReindexIndex(stmt->relation, stmt->force);
2000-02-18 10:30:20 +01:00
break;
case REINDEX_TABLE:
CheckOwnership(stmt->relation, false);
ReindexTable(stmt->relation, stmt->force);
2000-02-18 10:30:20 +01:00
break;
case REINDEX_DATABASE:
ReindexDatabase(stmt->name, stmt->force, false);
2000-02-18 10:30:20 +01:00
break;
}
break;
}
break;
case T_CreateConversionStmt:
CreateConversionCommand((CreateConversionStmt *) parsetree);
break;
case T_CreateCastStmt:
CreateCast((CreateCastStmt *) parsetree);
break;
case T_DropCastStmt:
DropCast((DropCastStmt *) parsetree);
break;
case T_CreateOpClassStmt:
DefineOpClass((CreateOpClassStmt *) parsetree);
break;
case T_RemoveOpClassStmt:
RemoveOpClass((RemoveOpClassStmt *) parsetree);
break;
default:
elog(ERROR, "ProcessUtility: command #%d unsupported",
nodeTag(parsetree));
break;
}
}