aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/remove.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/remove.c')
-rw-r--r--src/backend/commands/remove.c435
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);
+}