1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
1997-05-22 02:17:24 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.17 1997/05/22 00:15:36 scrappy Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "parser/dbcommands.h"
|
|
|
|
#include "access/xact.h"
|
1997-04-02 06:06:32 +02:00
|
|
|
#include "access/heapam.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "catalog/catalog.h"
|
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
|
|
|
|
#include "commands/async.h"
|
|
|
|
#include "commands/cluster.h"
|
|
|
|
#include "commands/command.h"
|
|
|
|
#include "commands/copy.h"
|
|
|
|
#include "commands/creatinh.h"
|
1997-04-02 06:06:32 +02:00
|
|
|
#include "commands/sequence.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "commands/defrem.h"
|
|
|
|
#include "commands/purge.h"
|
|
|
|
#include "commands/rename.h"
|
|
|
|
#include "commands/view.h"
|
|
|
|
#include "commands/version.h"
|
|
|
|
#include "commands/vacuum.h"
|
|
|
|
#include "commands/recipe.h"
|
|
|
|
#include "commands/explain.h"
|
|
|
|
|
|
|
|
#include "nodes/parsenodes.h"
|
1996-11-08 07:02:30 +01:00
|
|
|
#include "../backend/parser/parse.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/acl.h"
|
|
|
|
#include "utils/palloc.h"
|
|
|
|
#include "rewrite/rewriteRemove.h"
|
|
|
|
#include "rewrite/rewriteDefine.h"
|
|
|
|
#include "tcop/tcopdebug.h"
|
|
|
|
#include "tcop/dest.h"
|
1997-04-02 20:24:52 +02:00
|
|
|
#include "tcop/variable.h"
|
1996-11-11 05:54:54 +01:00
|
|
|
#include "tcop/utility.h"
|
1996-11-10 03:27:15 +01:00
|
|
|
#include "fmgr.h" /* For load_file() */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#ifndef NO_SECURITY
|
|
|
|
#include "miscadmin.h"
|
|
|
|
#include "utils/acl.h"
|
|
|
|
#include "utils/syscache.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------
|
1996-11-02 03:03:13 +01:00
|
|
|
* CHECK_IF_ABORTED() is used to avoid doing unnecessary
|
|
|
|
* processing within an aborted transaction block.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
#define CHECK_IF_ABORTED() \
|
|
|
|
if (IsAbortedTransactionBlockState()) { \
|
1996-11-02 03:03:13 +01:00
|
|
|
elog(NOTICE, "(transaction aborted): %s", \
|
|
|
|
"queries ignored until END"); \
|
|
|
|
commandTag = "*ABORT STATE*"; \
|
|
|
|
break; \
|
1996-07-09 08:22:35 +02:00
|
|
|
} \
|
|
|
|
|
|
|
|
/* ----------------
|
1996-11-02 03:03:13 +01:00
|
|
|
* general utility function invoker
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ProcessUtility(Node *parsetree,
|
1996-11-02 03:03:13 +01:00
|
|
|
CommandDest dest)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
|
|
|
char *commandTag = NULL;
|
|
|
|
char *relname;
|
|
|
|
char *relationName;
|
|
|
|
char *userName;
|
|
|
|
|
|
|
|
userName = GetPgUserName();
|
|
|
|
|
|
|
|
switch (nodeTag(parsetree)) {
|
1996-11-02 03:03:13 +01:00
|
|
|
/* ********************************
|
|
|
|
* transactions
|
|
|
|
* ********************************
|
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
case T_TransactionStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
{
|
|
|
|
TransactionStmt *stmt = (TransactionStmt *)parsetree;
|
|
|
|
switch (stmt->command) {
|
|
|
|
case BEGIN_TRANS:
|
|
|
|
commandTag = "BEGIN";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
BeginTransactionBlock();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case END_TRANS:
|
|
|
|
commandTag = "END";
|
|
|
|
EndTransactionBlock();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ABORT_TRANS:
|
|
|
|
commandTag = "ABORT";
|
|
|
|
UserAbortTransactionBlock();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
/* ********************************
|
|
|
|
* portal manipulation
|
|
|
|
* ********************************
|
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
case T_ClosePortalStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
{
|
|
|
|
ClosePortalStmt *stmt = (ClosePortalStmt *)parsetree;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
commandTag = "CLOSE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
PerformPortalClose(stmt->portalname, dest);
|
|
|
|
}
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
case T_FetchStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
{
|
|
|
|
FetchStmt *stmt = (FetchStmt *)parsetree;
|
|
|
|
char *portalName = stmt->portalname;
|
|
|
|
bool forward;
|
|
|
|
int count;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
commandTag = "FETCH";
|
|
|
|
CHECK_IF_ABORTED();
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
forward = (bool)(stmt->direction == FORWARD);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
/* parser ensures that count is >= 0 and
|
|
|
|
'fetch ALL' -> 0 */
|
|
|
|
|
|
|
|
count = stmt->howMany;
|
|
|
|
PerformPortalFetch(portalName, forward, count, commandTag, dest);
|
|
|
|
}
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
/* ********************************
|
|
|
|
* relation and attribute manipulation
|
|
|
|
* ********************************
|
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
case T_CreateStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
DefineRelation((CreateStmt *)parsetree);
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
case T_DestroyStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
{
|
|
|
|
DestroyStmt *stmt = (DestroyStmt *)parsetree;
|
|
|
|
List *arg;
|
|
|
|
List *args = stmt->relNames;
|
1997-04-02 06:06:32 +02:00
|
|
|
Relation rel;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
commandTag = "DROP";
|
|
|
|
CHECK_IF_ABORTED();
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
foreach (arg, args) {
|
|
|
|
relname = strVal(lfirst(arg));
|
|
|
|
if (IsSystemRelationName(relname))
|
|
|
|
elog(WARN, "class \"%-.*s\" is a system catalog",
|
|
|
|
NAMEDATALEN, relname);
|
1997-04-02 06:06:32 +02:00
|
|
|
rel = heap_openr (relname);
|
|
|
|
if ( RelationIsValid (rel) )
|
|
|
|
{
|
|
|
|
if ( stmt->sequence &&
|
|
|
|
rel->rd_rel->relkind != RELKIND_SEQUENCE )
|
|
|
|
elog (WARN, "Use DROP TABLE to drop table '%s'",
|
|
|
|
relname);
|
|
|
|
if ( !(stmt->sequence) &&
|
|
|
|
rel->rd_rel->relkind == RELKIND_SEQUENCE )
|
|
|
|
elog (WARN, "Use DROP SEQUENCE to drop sequence '%s'",
|
|
|
|
relname);
|
|
|
|
heap_close (rel);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
#ifndef NO_SECURITY
|
1996-11-02 03:03:13 +01:00
|
|
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
|
|
|
elog(WARN, "you do not own class \"%-.*s\"",
|
|
|
|
NAMEDATALEN, relname);
|
1996-07-09 08:22:35 +02:00
|
|
|
#endif
|
1996-11-02 03:03:13 +01:00
|
|
|
}
|
|
|
|
foreach (arg, args) {
|
|
|
|
relname = strVal(lfirst(arg));
|
|
|
|
RemoveRelation(relname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
case T_PurgeStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
{
|
|
|
|
PurgeStmt *stmt = (PurgeStmt *)parsetree;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
commandTag = "PURGE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
RelationPurge(stmt->relname,
|
|
|
|
stmt->beforeDate, /* absolute time string */
|
|
|
|
stmt->afterDate); /* relative time string */
|
|
|
|
}
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
case T_CopyStmt:
|
1996-11-02 03:03:13 +01:00
|
|
|
{
|
|
|
|
CopyStmt *stmt = (CopyStmt *)parsetree;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
commandTag = "COPY";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
/* Free up file descriptors - going to do a read... */
|
|
|
|
closeOneVfd();
|
|
|
|
|
1996-11-02 03:03:13 +01:00
|
|
|
DoCopy(stmt->relname,
|
|
|
|
stmt->binary,
|
|
|
|
stmt->oids,
|
|
|
|
(bool)(stmt->direction == FROM),
|
|
|
|
(bool)(stmt->filename == NULL),
|
|
|
|
/* null filename means copy to/from stdout/stdin,
|
|
|
|
rather than to/from a file.
|
|
|
|
*/
|
|
|
|
stmt->filename,
|
|
|
|
stmt->delimiter);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_AddAttrStmt:
|
|
|
|
{
|
|
|
|
AddAttrStmt *stmt = (AddAttrStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "ADD";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
/* owner checking done in PerformAddAttribute (now recursive) */
|
|
|
|
PerformAddAttribute(stmt->relname,
|
|
|
|
userName,
|
|
|
|
stmt->inh,
|
|
|
|
stmt->colDef);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* schema
|
|
|
|
*/
|
|
|
|
case T_RenameStmt:
|
|
|
|
{
|
|
|
|
RenameStmt *stmt = (RenameStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "RENAME";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
relname = stmt->relname;
|
|
|
|
if (IsSystemRelationName(relname))
|
|
|
|
elog(WARN, "class \"%s\" is a system catalog",
|
|
|
|
relname);
|
|
|
|
#ifndef NO_SECURITY
|
|
|
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
|
|
|
elog(WARN, "you do not own class \"%s\"",
|
|
|
|
relname);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* XXX using len == 3 to tell the difference
|
|
|
|
* between "rename rel to newrel" and
|
|
|
|
* "rename att in rel to newatt" will not
|
|
|
|
* work soon because "rename type/operator/rule"
|
|
|
|
* stuff is being added. - cim 10/24/90
|
|
|
|
* ----------------
|
|
|
|
* [another piece of amuzing but useless anecdote -- ay]
|
|
|
|
*/
|
|
|
|
if (stmt->column == NULL) {
|
|
|
|
/* ----------------
|
|
|
|
* rename relation
|
|
|
|
*
|
|
|
|
* Note: we also rename the "type" tuple
|
|
|
|
* corresponding to the relation.
|
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
renamerel(relname, /* old name */
|
|
|
|
stmt->newname); /* new name */
|
|
|
|
TypeRename(relname, /* old name */
|
|
|
|
stmt->newname); /* new name */
|
|
|
|
} else {
|
|
|
|
/* ----------------
|
|
|
|
* rename attribute
|
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
renameatt(relname, /* relname */
|
|
|
|
stmt->column, /* old att name */
|
|
|
|
stmt->newname, /* new att name */
|
|
|
|
userName,
|
|
|
|
stmt->inh); /* recursive? */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_ChangeACLStmt:
|
|
|
|
{
|
|
|
|
ChangeACLStmt *stmt = (ChangeACLStmt *)parsetree;
|
|
|
|
List *i;
|
|
|
|
AclItem *aip;
|
|
|
|
unsigned modechg;
|
|
|
|
|
|
|
|
commandTag = "CHANGE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
aip = stmt->aclitem;
|
|
|
|
modechg = stmt->modechg;
|
|
|
|
#ifndef NO_SECURITY
|
|
|
|
foreach (i, stmt->relNames) {
|
|
|
|
relname = strVal(lfirst(i));
|
|
|
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
|
|
|
elog(WARN, "you do not own class \"%-.*s\"",
|
|
|
|
NAMEDATALEN, relname);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
foreach (i, stmt->relNames) {
|
|
|
|
relname = strVal(lfirst(i));
|
|
|
|
ChangeAcl(relname, aip, modechg);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* ********************************
|
|
|
|
* object creation / destruction
|
|
|
|
* ********************************
|
|
|
|
*/
|
|
|
|
case T_DefineStmt:
|
|
|
|
{
|
|
|
|
DefineStmt *stmt = (DefineStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
switch(stmt->defType) {
|
|
|
|
case OPERATOR:
|
|
|
|
DefineOperator(stmt->defname, /* operator name */
|
|
|
|
stmt->definition); /* rest */
|
|
|
|
break;
|
|
|
|
case P_TYPE:
|
|
|
|
{
|
|
|
|
DefineType (stmt->defname, stmt->definition);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AGGREGATE:
|
|
|
|
DefineAggregate(stmt->defname, /*aggregate name */
|
|
|
|
stmt->definition); /* rest */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-10-31 10:08:10 +01:00
|
|
|
case T_ViewStmt: /* CREATE VIEW */
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
|
|
|
ViewStmt *stmt = (ViewStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
DefineView (stmt->viewname, stmt->query); /* retrieve parsetree */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-10-31 10:08:10 +01:00
|
|
|
case T_ProcedureStmt: /* CREATE FUNCTION */
|
1996-07-09 08:22:35 +02:00
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
1996-10-31 10:08:10 +01:00
|
|
|
CreateFunction((ProcedureStmt *)parsetree, dest); /* everything */
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
|
|
|
|
1996-10-31 10:08:10 +01:00
|
|
|
case T_IndexStmt: /* CREATE INDEX */
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
|
|
|
IndexStmt *stmt = (IndexStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
/* XXX no support for ARCHIVE indices, yet */
|
|
|
|
DefineIndex(stmt->relname, /* relation name */
|
|
|
|
stmt->idxname, /* index name */
|
|
|
|
stmt->accessMethod, /* am name */
|
|
|
|
stmt->indexParams, /* parameters */
|
|
|
|
stmt->withClause,
|
1996-11-13 21:56:15 +01:00
|
|
|
stmt->unique,
|
1996-07-09 08:22:35 +02:00
|
|
|
(Expr*)stmt->whereClause,
|
|
|
|
stmt->rangetable);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-10-31 10:08:10 +01:00
|
|
|
case T_RuleStmt: /* CREATE RULE */
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
|
|
|
RuleStmt *stmt = (RuleStmt *)parsetree;
|
1997-03-12 21:48:48 +01:00
|
|
|
int aclcheck_result;
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#ifndef NO_SECURITY
|
|
|
|
relname = stmt->object->relname;
|
1997-03-12 21:48:48 +01:00
|
|
|
aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
|
|
|
|
if(aclcheck_result != ACLCHECK_OK)
|
|
|
|
elog(WARN, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
|
1996-07-09 08:22:35 +02:00
|
|
|
#endif
|
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
DefineQueryRewrite(stmt);
|
|
|
|
}
|
|
|
|
break;
|
1997-04-02 06:06:32 +02:00
|
|
|
|
|
|
|
case T_CreateSeqStmt:
|
|
|
|
commandTag = "CREATE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
DefineSequence((CreateSeqStmt *)parsetree);
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
case T_ExtendStmt:
|
|
|
|
{
|
|
|
|
ExtendStmt *stmt = (ExtendStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "EXTEND";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
ExtendIndex(stmt->idxname, /* index name */
|
|
|
|
(Expr*)stmt->whereClause, /* where */
|
|
|
|
stmt->rangetable);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_RemoveStmt:
|
|
|
|
{
|
|
|
|
RemoveStmt *stmt = (RemoveStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "DROP";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
switch(stmt->removeType) {
|
|
|
|
case INDEX:
|
|
|
|
relname = stmt->name;
|
|
|
|
if (IsSystemRelationName(relname))
|
|
|
|
elog(WARN, "class \"%s\" is a system catalog index",
|
|
|
|
relname);
|
|
|
|
#ifndef NO_SECURITY
|
|
|
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
1997-04-02 06:06:32 +02:00
|
|
|
elog(WARN, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
1996-07-09 08:22:35 +02:00
|
|
|
#endif
|
|
|
|
RemoveIndex(relname);
|
|
|
|
break;
|
|
|
|
case RULE:
|
|
|
|
{
|
|
|
|
char *rulename = stmt->name;
|
1997-03-12 21:48:48 +01:00
|
|
|
int aclcheck_result;
|
1996-07-09 08:22:35 +02:00
|
|
|
#ifndef NO_SECURITY
|
|
|
|
|
|
|
|
relationName = RewriteGetRuleEventRel(rulename);
|
1997-03-12 21:48:48 +01:00
|
|
|
aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
|
|
|
|
if(aclcheck_result != ACLCHECK_OK) {
|
|
|
|
elog(WARN, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
#endif
|
|
|
|
RemoveRewriteRule(rulename);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case P_TYPE:
|
|
|
|
#ifndef NO_SECURITY
|
|
|
|
/* XXX moved to remove.c */
|
|
|
|
#endif
|
|
|
|
RemoveType(stmt->name);
|
|
|
|
break;
|
|
|
|
case VIEW:
|
|
|
|
{
|
|
|
|
char *viewName = stmt->name;
|
|
|
|
char *ruleName;
|
|
|
|
extern char *RewriteGetRuleEventRel();
|
|
|
|
|
|
|
|
#ifndef NO_SECURITY
|
|
|
|
|
|
|
|
ruleName = MakeRetrieveViewRuleName(viewName);
|
|
|
|
relationName = RewriteGetRuleEventRel(ruleName);
|
|
|
|
if (!pg_ownercheck(userName, relationName, RELNAME))
|
1997-03-12 21:48:48 +01:00
|
|
|
elog(WARN, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
1996-07-09 08:22:35 +02:00
|
|
|
pfree(ruleName);
|
|
|
|
#endif
|
|
|
|
RemoveView(viewName);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-05-22 02:17:24 +02:00
|
|
|
|
|
|
|
case T_RemoveAggrStmt:
|
|
|
|
{
|
|
|
|
RemoveAggrStmt *stmt = (RemoveAggrStmt *)parsetree;
|
|
|
|
commandTag = "DROP";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
RemoveAggregate(stmt->aggname, stmt->aggtype);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
case T_RemoveFuncStmt:
|
|
|
|
{
|
|
|
|
RemoveFuncStmt *stmt = (RemoveFuncStmt *)parsetree;
|
|
|
|
commandTag = "DROP";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
RemoveFunction(stmt->funcname,
|
|
|
|
length(stmt->args),
|
|
|
|
stmt->args);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_RemoveOperStmt:
|
|
|
|
{
|
|
|
|
RemoveOperStmt *stmt = (RemoveOperStmt *)parsetree;
|
|
|
|
char* type1 = (char*) NULL;
|
|
|
|
char *type2 = (char*) NULL;
|
|
|
|
|
|
|
|
commandTag = "DROP";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
if (lfirst(stmt->args)!=NULL)
|
|
|
|
type1 = strVal(lfirst(stmt->args));
|
|
|
|
if (lsecond(stmt->args)!=NULL)
|
|
|
|
type2 = strVal(lsecond(stmt->args));
|
|
|
|
RemoveOperator(stmt->opname, type1, type2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_VersionStmt:
|
|
|
|
{
|
|
|
|
elog(WARN, "CREATE VERSION is not currently implemented");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_CreatedbStmt:
|
|
|
|
{
|
|
|
|
CreatedbStmt *stmt = (CreatedbStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "CREATEDB";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
createdb(stmt->dbname);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_DestroydbStmt:
|
|
|
|
{
|
|
|
|
DestroydbStmt *stmt = (DestroydbStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "DESTROYDB";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
destroydb(stmt->dbname);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Query-level asynchronous notification */
|
|
|
|
case T_NotifyStmt:
|
|
|
|
{
|
|
|
|
NotifyStmt *stmt = (NotifyStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "NOTIFY";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
Async_Notify(stmt->relname);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_ListenStmt:
|
|
|
|
{
|
|
|
|
ListenStmt *stmt = (ListenStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "LISTEN";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
Async_Listen(stmt->relname,MasterPid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* ********************************
|
|
|
|
* dynamic loader
|
|
|
|
* ********************************
|
|
|
|
*/
|
|
|
|
case T_LoadStmt:
|
|
|
|
{
|
|
|
|
LoadStmt *stmt = (LoadStmt *)parsetree;
|
|
|
|
FILE *fp, *fopen();
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
commandTag = "LOAD";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
filename = stmt->filename;
|
|
|
|
closeAllVfds();
|
|
|
|
if ((fp = fopen(filename, "r")) == NULL)
|
|
|
|
elog(WARN, "LOAD: could not open file %s", filename);
|
|
|
|
fclose(fp);
|
|
|
|
load_file(filename);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_ClusterStmt:
|
|
|
|
{
|
|
|
|
ClusterStmt *stmt = (ClusterStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "CLUSTER";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
|
|
|
cluster(stmt->relname, stmt->indexname);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_VacuumStmt:
|
|
|
|
commandTag = "VACUUM";
|
|
|
|
CHECK_IF_ABORTED();
|
1997-01-13 04:45:33 +01:00
|
|
|
vacuum( ((VacuumStmt *) parsetree)->vacrel,
|
1997-04-23 08:09:36 +02:00
|
|
|
((VacuumStmt *) parsetree)->verbose,
|
|
|
|
((VacuumStmt *) parsetree)->analyze,
|
|
|
|
((VacuumStmt *) parsetree)->va_spec);
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_ExplainStmt:
|
|
|
|
{
|
|
|
|
ExplainStmt *stmt = (ExplainStmt *)parsetree;
|
|
|
|
|
|
|
|
commandTag = "EXPLAIN";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
|
1997-01-16 15:56:59 +01:00
|
|
|
ExplainQuery(stmt->query, stmt->verbose, dest);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* ********************************
|
|
|
|
Tioga-related statements
|
|
|
|
*********************************/
|
|
|
|
case T_RecipeStmt:
|
|
|
|
{
|
|
|
|
RecipeStmt* stmt = (RecipeStmt*)parsetree;
|
|
|
|
commandTag="EXECUTE RECIPE";
|
|
|
|
CHECK_IF_ABORTED();
|
|
|
|
beginRecipe(stmt);
|
|
|
|
}
|
|
|
|
break;
|
1997-04-02 20:24:52 +02:00
|
|
|
|
|
|
|
/* ********************************
|
|
|
|
* set variable statements
|
|
|
|
*********************************/
|
|
|
|
case T_VariableSetStmt:
|
|
|
|
{
|
|
|
|
VariableSetStmt *n = (VariableSetStmt *) parsetree;
|
|
|
|
SetPGVariable(n->name, n->value);
|
To: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [PATCHES] SET DateStyle patches
On Tue, 22 Apr 1997, Thomas Lockhart wrote:
> Some more patches! These (try to) finish implementing SET variable TO value
> for "DateStyle" (changed the name from simply "date" to be more descriptive).
> This is based on code from Martin and Bruce (?), which was easy to modify.
> The syntax is
>
> SET DateStyle TO 'iso'
> SET DateStyle TO 'postgres'
> SET DateStyle TO 'sql'
> SET DateStyle TO 'european'
> SET DateStyle TO 'noneuropean'
> SET DateStyle TO 'us' (same as "noneuropean")
> SET DateStyle TO 'default' (current same as "postgres,us")
>
> ("european" is just compared for the first 4 characters, and "noneuropean"
> is compared for the first 7 to allow less typing).
>
> Multiple arguments are allowed, so SET datestyle TO 'sql,euro' is valid.
>
> My mods also try to implement "SHOW variable" and "RESET variable", but
> that part just core dumps at the moment. I would guess that my errors
> are obvious to someone who knows what they are doing with the parser stuff,
> so if someone (Bruce and/or Martin??) could have it do the right thing
> we will have a more complete set of what we need.
>
> Also, I would like to have a floating point precision global variable to
> implement "SET precision TO 10" and perhaps "SET precision TO 10,2" for
> float8 and float4, but I don't know how to do that for integer types rather
> than strings. If someone is fixing the SHOW and RESET code, perhaps they can
> add some hooks for me to do the floats while they are at it.
>
> I've left some remnants of variable structures in the source code which
> I did not use in the interests of getting something working for v6.1.
> We'll have time to clean things up for the next release...
1997-04-23 05:18:27 +02:00
|
|
|
commandTag = "SET VARIABLE";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_VariableShowStmt:
|
|
|
|
{
|
1997-04-23 08:09:36 +02:00
|
|
|
VariableShowStmt *n = (VariableShowStmt *) parsetree;
|
To: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [PATCHES] SET DateStyle patches
On Tue, 22 Apr 1997, Thomas Lockhart wrote:
> Some more patches! These (try to) finish implementing SET variable TO value
> for "DateStyle" (changed the name from simply "date" to be more descriptive).
> This is based on code from Martin and Bruce (?), which was easy to modify.
> The syntax is
>
> SET DateStyle TO 'iso'
> SET DateStyle TO 'postgres'
> SET DateStyle TO 'sql'
> SET DateStyle TO 'european'
> SET DateStyle TO 'noneuropean'
> SET DateStyle TO 'us' (same as "noneuropean")
> SET DateStyle TO 'default' (current same as "postgres,us")
>
> ("european" is just compared for the first 4 characters, and "noneuropean"
> is compared for the first 7 to allow less typing).
>
> Multiple arguments are allowed, so SET datestyle TO 'sql,euro' is valid.
>
> My mods also try to implement "SHOW variable" and "RESET variable", but
> that part just core dumps at the moment. I would guess that my errors
> are obvious to someone who knows what they are doing with the parser stuff,
> so if someone (Bruce and/or Martin??) could have it do the right thing
> we will have a more complete set of what we need.
>
> Also, I would like to have a floating point precision global variable to
> implement "SET precision TO 10" and perhaps "SET precision TO 10,2" for
> float8 and float4, but I don't know how to do that for integer types rather
> than strings. If someone is fixing the SHOW and RESET code, perhaps they can
> add some hooks for me to do the floats while they are at it.
>
> I've left some remnants of variable structures in the source code which
> I did not use in the interests of getting something working for v6.1.
> We'll have time to clean things up for the next release...
1997-04-23 05:18:27 +02:00
|
|
|
GetPGVariable(n->name);
|
|
|
|
commandTag = "SHOW VARIABLE";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_VariableResetStmt:
|
|
|
|
{
|
1997-04-23 08:09:36 +02:00
|
|
|
VariableResetStmt *n = (VariableResetStmt *) parsetree;
|
To: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [PATCHES] SET DateStyle patches
On Tue, 22 Apr 1997, Thomas Lockhart wrote:
> Some more patches! These (try to) finish implementing SET variable TO value
> for "DateStyle" (changed the name from simply "date" to be more descriptive).
> This is based on code from Martin and Bruce (?), which was easy to modify.
> The syntax is
>
> SET DateStyle TO 'iso'
> SET DateStyle TO 'postgres'
> SET DateStyle TO 'sql'
> SET DateStyle TO 'european'
> SET DateStyle TO 'noneuropean'
> SET DateStyle TO 'us' (same as "noneuropean")
> SET DateStyle TO 'default' (current same as "postgres,us")
>
> ("european" is just compared for the first 4 characters, and "noneuropean"
> is compared for the first 7 to allow less typing).
>
> Multiple arguments are allowed, so SET datestyle TO 'sql,euro' is valid.
>
> My mods also try to implement "SHOW variable" and "RESET variable", but
> that part just core dumps at the moment. I would guess that my errors
> are obvious to someone who knows what they are doing with the parser stuff,
> so if someone (Bruce and/or Martin??) could have it do the right thing
> we will have a more complete set of what we need.
>
> Also, I would like to have a floating point precision global variable to
> implement "SET precision TO 10" and perhaps "SET precision TO 10,2" for
> float8 and float4, but I don't know how to do that for integer types rather
> than strings. If someone is fixing the SHOW and RESET code, perhaps they can
> add some hooks for me to do the floats while they are at it.
>
> I've left some remnants of variable structures in the source code which
> I did not use in the interests of getting something working for v6.1.
> We'll have time to clean things up for the next release...
1997-04-23 05:18:27 +02:00
|
|
|
ResetPGVariable(n->name);
|
|
|
|
commandTag = "RESET VARIABLE";
|
1997-04-02 20:24:52 +02:00
|
|
|
}
|
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* ********************************
|
|
|
|
* default
|
|
|
|
* ********************************
|
|
|
|
*/
|
|
|
|
default:
|
|
|
|
elog(WARN, "ProcessUtility: command #%d unsupported",
|
|
|
|
nodeTag(parsetree));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* tell fe/be or whatever that we're done.
|
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
EndCommand(commandTag, dest);
|
|
|
|
}
|
|
|
|
|