diff options
Diffstat (limited to 'src/backend/commands/remove.c')
-rw-r--r-- | src/backend/commands/remove.c | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c new file mode 100644 index 00000000000..95830c6cc08 --- /dev/null +++ b/src/backend/commands/remove.c @@ -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); +} |