mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
435
src/backend/commands/remove.c
Normal file
435
src/backend/commands/remove.c
Normal file
@ -0,0 +1,435 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* remove.c--
|
||||
* POSTGRES remove (function | type | operator ) utilty code.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.1.1.1 1996/07/09 06:21:22 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "c.h"
|
||||
|
||||
#include "access/attnum.h"
|
||||
#include "access/heapam.h"
|
||||
#include "access/htup.h"
|
||||
#include "access/skey.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/tqual.h" /* for NowTimeQual */
|
||||
#include "catalog/catname.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "utils/elog.h"
|
||||
|
||||
#include "miscadmin.h"
|
||||
|
||||
#include "catalog/pg_aggregate.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "parser/catalog_utils.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "fmgr.h"
|
||||
|
||||
/*
|
||||
* RemoveOperator --
|
||||
* Deletes an operator.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if name is invalid.
|
||||
* BadArg if type1 is invalid.
|
||||
* "WARN" if operator nonexistant.
|
||||
* ...
|
||||
*/
|
||||
void
|
||||
RemoveOperator(char *operatorName, /* operator name */
|
||||
char *typeName1, /* first type name */
|
||||
char *typeName2) /* optional second type name */
|
||||
{
|
||||
Relation relation;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tup;
|
||||
Oid typeId1 = InvalidOid;
|
||||
Oid typeId2 = InvalidOid;
|
||||
bool defined;
|
||||
ItemPointerData itemPointerData;
|
||||
Buffer buffer;
|
||||
ScanKeyData operatorKey[3];
|
||||
char *userName;
|
||||
|
||||
if (typeName1) {
|
||||
typeId1 = TypeGet(typeName1, &defined);
|
||||
if (!OidIsValid(typeId1)) {
|
||||
elog(WARN, "RemoveOperator: type '%s' does not exist", typeName1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeName2) {
|
||||
typeId2 = TypeGet(typeName2, &defined);
|
||||
if (!OidIsValid(typeId2)) {
|
||||
elog(WARN, "RemoveOperator: type '%s' does not exist", typeName2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScanKeyEntryInitialize(&operatorKey[0], 0x0,
|
||||
Anum_pg_operator_oprname,
|
||||
NameEqualRegProcedure,
|
||||
PointerGetDatum(operatorName));
|
||||
|
||||
ScanKeyEntryInitialize(&operatorKey[1], 0x0,
|
||||
Anum_pg_operator_oprleft,
|
||||
ObjectIdEqualRegProcedure,
|
||||
ObjectIdGetDatum(typeId1));
|
||||
|
||||
ScanKeyEntryInitialize(&operatorKey[2], 0x0,
|
||||
Anum_pg_operator_oprright,
|
||||
ObjectIdEqualRegProcedure,
|
||||
ObjectIdGetDatum(typeId2));
|
||||
|
||||
relation = heap_openr(OperatorRelationName);
|
||||
scan = heap_beginscan(relation, 0, NowTimeQual, 3, operatorKey);
|
||||
tup = heap_getnext(scan, 0, &buffer);
|
||||
if (HeapTupleIsValid(tup)) {
|
||||
#ifndef NO_SECURITY
|
||||
userName = GetPgUserName();
|
||||
if (!pg_ownercheck(userName,
|
||||
(char *) ObjectIdGetDatum(tup->t_oid),
|
||||
OPROID))
|
||||
elog(WARN, "RemoveOperator: operator '%s': permission denied",
|
||||
operatorName);
|
||||
#endif
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
heap_delete(relation, &itemPointerData);
|
||||
} else {
|
||||
if (OidIsValid(typeId1) && OidIsValid(typeId2)) {
|
||||
elog(WARN, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
|
||||
operatorName,
|
||||
typeName1,
|
||||
typeName2);
|
||||
} else if (OidIsValid(typeId1)) {
|
||||
elog(WARN, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
|
||||
operatorName,
|
||||
typeName1);
|
||||
} else {
|
||||
elog(WARN, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
|
||||
operatorName,
|
||||
typeName2);
|
||||
}
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_close(relation);
|
||||
}
|
||||
|
||||
#ifdef NOTYET
|
||||
/*
|
||||
* this stuff is to support removing all reference to a type
|
||||
* don't use it - pma 2/1/94
|
||||
*/
|
||||
/*
|
||||
* SingleOpOperatorRemove
|
||||
* Removes all operators that have operands or a result of type 'typeOid'.
|
||||
*/
|
||||
static void
|
||||
SingleOpOperatorRemove(Oid typeOid)
|
||||
{
|
||||
Relation rdesc;
|
||||
ScanKeyData key[3];
|
||||
HeapScanDesc sdesc;
|
||||
HeapTuple tup;
|
||||
ItemPointerData itemPointerData;
|
||||
Buffer buffer;
|
||||
static attnums[3] = { 7, 8, 9 }; /* left, right, return */
|
||||
register i;
|
||||
|
||||
ScanKeyEntryInitialize(&key[0],
|
||||
0, 0, ObjectIdEqualRegProcedure, (Datum)typeOid);
|
||||
rdesc = heap_openr(OperatorRelationName);
|
||||
for (i = 0; i < 3; ++i) {
|
||||
key[0].sk_attno = attnums[i];
|
||||
sdesc = heap_beginscan(rdesc, 0, NowTimeQual, 1, key);
|
||||
while (PointerIsValid(tup = heap_getnext(sdesc, 0, &buffer))) {
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
/* XXX LOCK not being passed */
|
||||
heap_delete(rdesc, &itemPointerData);
|
||||
}
|
||||
heap_endscan(sdesc);
|
||||
}
|
||||
heap_close(rdesc);
|
||||
}
|
||||
|
||||
/*
|
||||
* AttributeAndRelationRemove
|
||||
* Removes all entries in the attribute and relation relations
|
||||
* that contain entries of type 'typeOid'.
|
||||
* Currently nothing calls this code, it is untested.
|
||||
*/
|
||||
static void
|
||||
AttributeAndRelationRemove(Oid typeOid)
|
||||
{
|
||||
struct oidlist {
|
||||
Oid reloid;
|
||||
struct oidlist *next;
|
||||
};
|
||||
struct oidlist *oidptr, *optr;
|
||||
Relation rdesc;
|
||||
ScanKeyData key[1];
|
||||
HeapScanDesc sdesc;
|
||||
HeapTuple tup;
|
||||
ItemPointerData itemPointerData;
|
||||
Buffer buffer;
|
||||
|
||||
/*
|
||||
* Get the oid's of the relations to be removed by scanning the
|
||||
* entire attribute relation.
|
||||
* We don't need to remove the attributes here,
|
||||
* because amdestroy will remove all attributes of the relation.
|
||||
* XXX should check for duplicate relations
|
||||
*/
|
||||
|
||||
ScanKeyEntryInitialize(&key[0],
|
||||
0, 3, ObjectIdEqualRegProcedure, (Datum)typeOid);
|
||||
|
||||
oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
|
||||
oidptr->next = NULL;
|
||||
optr = oidptr;
|
||||
rdesc = heap_openr(AttributeRelationName);
|
||||
sdesc = heap_beginscan(rdesc, 0, NowTimeQual, 1, key);
|
||||
while (PointerIsValid(tup = heap_getnext(sdesc, 0, &buffer))) {
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
optr->reloid = ((AttributeTupleForm)GETSTRUCT(tup))->attrelid;
|
||||
optr->next = (struct oidlist *) palloc(sizeof(*oidptr));
|
||||
optr = optr->next;
|
||||
}
|
||||
optr->next = NULL;
|
||||
heap_endscan(sdesc);
|
||||
heap_close(rdesc);
|
||||
|
||||
|
||||
ScanKeyEntryInitialize(&key[0], 0,
|
||||
ObjectIdAttributeNumber,
|
||||
ObjectIdEqualRegProcedure, (Datum)0);
|
||||
optr = oidptr;
|
||||
rdesc = heap_openr(RelationRelationName);
|
||||
while (PointerIsValid((char *) optr->next)) {
|
||||
key[0].sk_argument = (Datum) (optr++)->reloid;
|
||||
sdesc = heap_beginscan(rdesc, 0, NowTimeQual, 1, key);
|
||||
tup = heap_getnext(sdesc, 0, &buffer);
|
||||
if (PointerIsValid(tup)) {
|
||||
char *name;
|
||||
|
||||
name = (((Form_pg_class)GETSTRUCT(tup))->relname).data;
|
||||
heap_destroy(name);
|
||||
}
|
||||
}
|
||||
heap_endscan(sdesc);
|
||||
heap_close(rdesc);
|
||||
}
|
||||
#endif /* NOTYET */
|
||||
|
||||
/*
|
||||
* TypeRemove
|
||||
* Removes the type 'typeName' and all attributes and relations that
|
||||
* use it.
|
||||
*/
|
||||
void
|
||||
RemoveType(char *typeName) /* type name to be removed */
|
||||
{
|
||||
Relation relation;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tup;
|
||||
Oid typeOid;
|
||||
ItemPointerData itemPointerData;
|
||||
static ScanKeyData typeKey[1] = {
|
||||
{ 0, Anum_pg_type_typname, NameEqualRegProcedure }
|
||||
};
|
||||
char *shadow_type;
|
||||
char *userName;
|
||||
|
||||
#ifndef NO_SECURITY
|
||||
userName = GetPgUserName();
|
||||
if (!pg_ownercheck(userName, typeName, TYPNAME))
|
||||
elog(WARN, "RemoveType: type '%s': permission denied",
|
||||
typeName);
|
||||
#endif
|
||||
|
||||
relation = heap_openr(TypeRelationName);
|
||||
fmgr_info(typeKey[0].sk_procedure, &typeKey[0].sk_func,
|
||||
&typeKey[0].sk_nargs);
|
||||
|
||||
/* Delete the primary type */
|
||||
|
||||
typeKey[0].sk_argument = PointerGetDatum(typeName);
|
||||
|
||||
scan = heap_beginscan(relation, 0, NowTimeQual, 1, typeKey);
|
||||
tup = heap_getnext(scan, 0, (Buffer *) 0);
|
||||
if (!HeapTupleIsValid(tup)) {
|
||||
heap_endscan(scan);
|
||||
heap_close(relation);
|
||||
elog(WARN, "RemoveType: type '%s' does not exist",
|
||||
typeName);
|
||||
}
|
||||
typeOid = tup->t_oid;
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
heap_delete(relation, &itemPointerData);
|
||||
heap_endscan(scan);
|
||||
|
||||
/* Now, Delete the "array of" that type */
|
||||
shadow_type = makeArrayTypeName(typeName);
|
||||
typeKey[0].sk_argument = NameGetDatum(shadow_type);
|
||||
|
||||
scan = heap_beginscan(relation, 0, NowTimeQual,
|
||||
1, (ScanKey) typeKey);
|
||||
tup = heap_getnext(scan, 0, (Buffer *) 0);
|
||||
|
||||
if (!HeapTupleIsValid(tup))
|
||||
{
|
||||
elog(WARN, "RemoveType: type '%s': array stub not found",
|
||||
typeName);
|
||||
}
|
||||
typeOid = tup->t_oid;
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
heap_delete(relation, &itemPointerData);
|
||||
heap_endscan(scan);
|
||||
|
||||
heap_close(relation);
|
||||
}
|
||||
|
||||
/*
|
||||
* RemoveFunction --
|
||||
* Deletes a function.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if name is invalid.
|
||||
* "WARN" if function nonexistant.
|
||||
* ...
|
||||
*/
|
||||
void
|
||||
RemoveFunction(char *functionName, /* function name to be removed */
|
||||
int nargs,
|
||||
List *argNameList /* list of TypeNames */)
|
||||
{
|
||||
Relation relation;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tup;
|
||||
Buffer buffer = InvalidBuffer;
|
||||
bool bufferUsed = FALSE;
|
||||
Oid argList[8];
|
||||
Form_pg_proc the_proc;
|
||||
ItemPointerData itemPointerData;
|
||||
static ScanKeyData key[3] = {
|
||||
{ 0, Anum_pg_proc_proname, NameEqualRegProcedure }
|
||||
};
|
||||
char *userName;
|
||||
char *typename;
|
||||
int i;
|
||||
|
||||
memset(argList, 0, 8 * sizeof(Oid));
|
||||
for (i=0; i<nargs; i++) {
|
||||
/* typename = ((TypeName*)(lfirst(argNameList)))->name; */
|
||||
typename = strVal(lfirst(argNameList));
|
||||
argNameList = lnext(argNameList);
|
||||
|
||||
if (strcmp(typename, "opaque") == 0)
|
||||
argList[i] = 0;
|
||||
else {
|
||||
tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typename),
|
||||
0,0,0);
|
||||
|
||||
if (!HeapTupleIsValid(tup)) {
|
||||
elog(WARN, "RemoveFunction: type '%s' not found",typename);
|
||||
}
|
||||
argList[i] = tup->t_oid;
|
||||
}
|
||||
}
|
||||
|
||||
tup = SearchSysCacheTuple(PRONAME, PointerGetDatum(functionName),
|
||||
Int32GetDatum(nargs),
|
||||
PointerGetDatum(argList),0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
func_error("RemoveFunction", functionName, nargs, (int*)argList);
|
||||
|
||||
#ifndef NO_SECURITY
|
||||
userName = GetPgUserName();
|
||||
if (!pg_func_ownercheck(userName, functionName, nargs, argList)) {
|
||||
elog(WARN, "RemoveFunction: function '%s': permission denied",
|
||||
functionName);
|
||||
}
|
||||
#endif
|
||||
|
||||
key[0].sk_argument = PointerGetDatum(functionName);
|
||||
|
||||
fmgr_info(key[0].sk_procedure, &key[0].sk_func, &key[0].sk_nargs);
|
||||
|
||||
relation = heap_openr(ProcedureRelationName);
|
||||
scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
|
||||
|
||||
do { /* hope this is ok because it's indexed */
|
||||
if (bufferUsed) {
|
||||
ReleaseBuffer(buffer);
|
||||
bufferUsed = FALSE;
|
||||
}
|
||||
tup = heap_getnext(scan, 0, (Buffer *) &buffer);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
break;
|
||||
bufferUsed = TRUE;
|
||||
the_proc = (Form_pg_proc) GETSTRUCT(tup);
|
||||
} while ( (namestrcmp(&(the_proc->proname), functionName) == 0) &&
|
||||
(the_proc->pronargs != nargs ||
|
||||
!oid8eq(&(the_proc->proargtypes[0]), &argList[0])));
|
||||
|
||||
|
||||
if (!HeapTupleIsValid(tup) || namestrcmp(&(the_proc->proname),
|
||||
functionName) != 0)
|
||||
{
|
||||
heap_endscan(scan);
|
||||
heap_close(relation);
|
||||
func_error("RemoveFunction", functionName,nargs, (int*)argList);
|
||||
}
|
||||
|
||||
/* ok, function has been found */
|
||||
|
||||
if (the_proc->prolang == INTERNALlanguageId)
|
||||
elog(WARN, "RemoveFunction: function \"%-.*s\" is built-in",
|
||||
NAMEDATALEN, functionName);
|
||||
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
heap_delete(relation, &itemPointerData);
|
||||
heap_endscan(scan);
|
||||
heap_close(relation);
|
||||
}
|
||||
|
||||
void
|
||||
RemoveAggregate(char *aggName)
|
||||
{
|
||||
Relation relation;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tup;
|
||||
ItemPointerData itemPointerData;
|
||||
static ScanKeyData key[3] = {
|
||||
{ 0, Anum_pg_aggregate_aggname, NameEqualRegProcedure }
|
||||
};
|
||||
|
||||
key[0].sk_argument = PointerGetDatum(aggName);
|
||||
|
||||
fmgr_info(key[0].sk_procedure, &key[0].sk_func, &key[0].sk_nargs);
|
||||
relation = heap_openr(AggregateRelationName);
|
||||
scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
|
||||
tup = heap_getnext(scan, 0, (Buffer *) 0);
|
||||
if (!HeapTupleIsValid(tup)) {
|
||||
heap_endscan(scan);
|
||||
heap_close(relation);
|
||||
elog(WARN, "RemoveAggregate: aggregate '%s' does not exist",
|
||||
aggName);
|
||||
}
|
||||
ItemPointerCopy(&tup->t_ctid, &itemPointerData);
|
||||
heap_delete(relation, &itemPointerData);
|
||||
heap_endscan(scan);
|
||||
heap_close(relation);
|
||||
}
|
Reference in New Issue
Block a user