remove.c 9.9 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * remove.c
4
 *	  POSTGRES remove (function | type | operator ) utilty code.
5 6 7 8 9
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
10
 *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.37 1999/09/18 19:06:40 tgl Exp $
11 12 13
 *
 *-------------------------------------------------------------------------
 */
B
Bruce Momjian 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26
#include "postgres.h"

#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/syscache.h"

27 28

/*
B
Bruce Momjian 已提交
29
 * RemoveOperator
30
 *		Deletes an operator.
31 32
 *
 * Exceptions:
33 34 35 36
 *		BadArg if name is invalid.
 *		BadArg if type1 is invalid.
 *		"WARN" if operator nonexistent.
 *		...
37 38
 */
void
39 40 41
RemoveOperator(char *operatorName,		/* operator name */
			   char *typeName1, /* first type name */
			   char *typeName2) /* optional second type name */
42
{
43 44 45 46 47 48
	Relation	relation;
	HeapTuple	tup;
	Oid			typeId1 = InvalidOid;
	Oid			typeId2 = InvalidOid;
	bool		defined;
	char	   *userName;
49
	char		oprtype;
50

51 52 53 54 55
	if (typeName1)
	{
		typeId1 = TypeGet(typeName1, &defined);
		if (!OidIsValid(typeId1))
		{
56
			elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1);
57 58
			return;
		}
59
	}
60 61 62 63 64 65

	if (typeName2)
	{
		typeId2 = TypeGet(typeName2, &defined);
		if (!OidIsValid(typeId2))
		{
66
			elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2);
67 68
			return;
		}
69
	}
70

71 72 73 74 75 76 77
	if (OidIsValid(typeId1) && OidIsValid(typeId2))
		oprtype = 'b';
	else if (OidIsValid(typeId1))
		oprtype = 'l';
	else
		oprtype = 'r';

78 79
	relation = heap_openr(OperatorRelationName, RowExclusiveLock);

80
	tup = SearchSysCacheTupleCopy(OPRNAME,
81 82 83 84 85
								  PointerGetDatum(operatorName),
								  ObjectIdGetDatum(typeId1),
								  ObjectIdGetDatum(typeId2),
								  CharGetDatum(oprtype));

86 87
	if (HeapTupleIsValid(tup))
	{
88
#ifndef NO_SECURITY
89 90
		userName = GetPgUserName();
		if (!pg_ownercheck(userName,
91
						   (char *) ObjectIdGetDatum(tup->t_data->t_oid),
92
						   OPROID))
93
			elog(ERROR, "RemoveOperator: operator '%s': permission denied",
94
				 operatorName);
95
#endif
V
Vadim B. Mikheev 已提交
96
		heap_delete(relation, &tup->t_self, NULL);
97
	}
98 99 100 101
	else
	{
		if (OidIsValid(typeId1) && OidIsValid(typeId2))
		{
102
			elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
103 104 105 106 107 108
				 operatorName,
				 typeName1,
				 typeName2);
		}
		else if (OidIsValid(typeId1))
		{
109
			elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
110 111 112 113 114
				 operatorName,
				 typeName1);
		}
		else
		{
115
			elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
116 117 118 119
				 operatorName,
				 typeName2);
		}
	}
120
	pfree(tup);
121
	heap_close(relation, RowExclusiveLock);
122 123 124 125 126 127 128 129
}

#ifdef NOTYET
/*
 * this stuff is to support removing all reference to a type
 * don't use it  - pma 2/1/94
 */
/*
130 131
 *	SingleOpOperatorRemove
 *		Removes all operators that have operands or a result of type 'typeOid'.
132 133 134 135
 */
static void
SingleOpOperatorRemove(Oid typeOid)
{
136
	Relation	rel;
137
	ScanKeyData key[3];
138
	HeapScanDesc scan;
139 140
	HeapTuple	tup;
	static		attnums[3] = {7, 8, 9}; /* left, right, return */
141
	int			i;
142 143

	ScanKeyEntryInitialize(&key[0],
144
						   0, 0, F_OIDEQ, (Datum) typeOid);
145
	rel = heap_openr(OperatorRelationName, RowExclusiveLock);
146 147 148
	for (i = 0; i < 3; ++i)
	{
		key[0].sk_attno = attnums[i];
149 150
		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
V
Vadim B. Mikheev 已提交
151
			heap_delete(rel, &tup->t_self, NULL);
152
		heap_endscan(scan);
153
	}
154
	heap_close(rel, RowExclusiveLock);
155 156 157
}

/*
158 159 160 161
 *	AttributeAndRelationRemove
 *		Removes all entries in the attribute and relation relations
 *		that contain entries of type 'typeOid'.
 *		Currently nothing calls this code, it is untested.
162 163 164 165
 */
static void
AttributeAndRelationRemove(Oid typeOid)
{
166 167
	struct oidlist
	{
168
		Oid			reloid;
169 170 171
		struct oidlist *next;
	};
	struct oidlist *oidptr,
172
			   *optr;
173
	Relation	rel;
174
	ScanKeyData key[1];
175
	HeapScanDesc scan;
176
	HeapTuple	tup;
177 178 179 180 181 182 183 184 185

	/*
	 * 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],
186
						   0, 3, F_OIDEQ, (Datum) typeOid);
187 188 189 190

	oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
	oidptr->next = NULL;
	optr = oidptr;
191
	rel = heap_openr(AttributeRelationName, AccessShareLock);
192 193
	scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
	while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
194
	{
195
		optr->reloid = ((Form_pg_attribute) GETSTRUCT(tup))->attrelid;
196 197
		optr->next = (struct oidlist *) palloc(sizeof(*oidptr));
		optr = optr->next;
198
	}
199
	optr->next = NULL;
200
	heap_endscan(scan);
201
	heap_close(rel, AccessShareLock);
202

203
	optr = oidptr;
204 205 206

	ScanKeyEntryInitialize(&key[0], 0,
						   ObjectIdAttributeNumber,
B
Bruce Momjian 已提交
207
						   F_OIDEQ, (Datum) 0);
208 209
	/* get RowExclusiveLock because heap_destroy will need it */
	rel = heap_openr(RelationRelationName, RowExclusiveLock);
210 211 212
	while (PointerIsValid((char *) optr->next))
	{
		key[0].sk_argument = (Datum) (optr++)->reloid;
213 214 215
		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
		tup = heap_getnext(scan, 0);
		if (HeapTupleIsValid(tup))
216
		{
217
			char	   *name;
218 219

			name = (((Form_pg_class) GETSTRUCT(tup))->relname).data;
220
			heap_destroy_with_catalog(name);
221
		}
222
		heap_endscan(scan);
223
	}
224
	heap_close(rel, RowExclusiveLock);
225
}
226

227
#endif	 /* NOTYET */
228 229

/*
230 231 232
 *	TypeRemove
 *		Removes the type 'typeName' and all attributes and relations that
 *		use it.
233 234
 */
void
235
RemoveType(char *typeName)		/* type name to be removed */
236
{
237 238 239 240 241
	Relation	relation;
	HeapTuple	tup;
	Oid			typeOid;
	char	   *shadow_type;
	char	   *userName;
242

243
#ifndef NO_SECURITY
244 245
	userName = GetPgUserName();
	if (!pg_ownercheck(userName, typeName, TYPNAME))
246
		elog(ERROR, "RemoveType: type '%s': permission denied",
247
			 typeName);
248
#endif
249

250 251
	relation = heap_openr(TypeRelationName, RowExclusiveLock);

252
	tup = SearchSysCacheTuple(TYPNAME,
253 254
							  PointerGetDatum(typeName),
							  0, 0, 0);
255 256
	if (!HeapTupleIsValid(tup))
	{
257
		heap_close(relation, RowExclusiveLock);
258
		elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
259
	}
260

261
	typeOid = tup->t_data->t_oid;
V
Vadim B. Mikheev 已提交
262
	heap_delete(relation, &tup->t_self, NULL);
263 264 265

	/* Now, Delete the "array of" that type */
	shadow_type = makeArrayTypeName(typeName);
266
	tup = SearchSysCacheTuple(TYPNAME,
267 268
							  PointerGetDatum(shadow_type),
							  0, 0, 0);
269
	if (!HeapTupleIsValid(tup))
270
	{
271 272
		heap_close(relation, RowExclusiveLock);
		elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
273
	}
274

V
Vadim B. Mikheev 已提交
275
	heap_delete(relation, &tup->t_self, NULL);
276

277
	heap_close(relation, RowExclusiveLock);
278 279 280
}

/*
B
Bruce Momjian 已提交
281
 * RemoveFunction
282
 *		Deletes a function.
283 284
 *
 * Exceptions:
285 286 287
 *		BadArg if name is invalid.
 *		"WARN" if function nonexistent.
 *		...
288 289
 */
void
290 291
RemoveFunction(char *functionName,		/* function name to be removed */
			   int nargs,
292
			   List *argNameList /* list of TypeNames */ )
293
{
294 295 296 297 298 299
	Relation	relation;
	HeapTuple	tup;
	Oid			argList[8];
	char	   *userName;
	char	   *typename;
	int			i;
300

301

B
Bruce Momjian 已提交
302
	MemSet(argList, 0, 8 * sizeof(Oid));
303 304 305 306 307 308 309 310 311
	for (i = 0; i < nargs; i++)
	{
		typename = strVal(lfirst(argNameList));
		argNameList = lnext(argNameList);

		if (strcmp(typename, "opaque") == 0)
			argList[i] = 0;
		else
		{
312 313
			tup = SearchSysCacheTuple(TYPNAME,
									  PointerGetDatum(typename),
314 315 316
									  0, 0, 0);

			if (!HeapTupleIsValid(tup))
317
				elog(ERROR, "RemoveFunction: type '%s' not found", typename);
318
			argList[i] = tup->t_data->t_oid;
319
		}
320
	}
321

322
#ifndef NO_SECURITY
323 324 325
	userName = GetPgUserName();
	if (!pg_func_ownercheck(userName, functionName, nargs, argList))
	{
326
		elog(ERROR, "RemoveFunction: function '%s': permission denied",
327
			 functionName);
328
	}
329 330
#endif

331
	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
332
	tup = SearchSysCacheTuple(PRONAME,
333 334 335 336
							  PointerGetDatum(functionName),
							  Int32GetDatum(nargs),
							  PointerGetDatum(argList),
							  0);
337

338
	if (!HeapTupleIsValid(tup))
339
	{
340
		heap_close(relation, RowExclusiveLock);
341
		func_error("RemoveFunction", functionName, nargs, argList, NULL);
342
	}
343

344 345
	if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
	{
346
		heap_close(relation, RowExclusiveLock);
347
		elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
348
	}
349

V
Vadim B. Mikheev 已提交
350
	heap_delete(relation, &tup->t_self, NULL);
351

352
	heap_close(relation, RowExclusiveLock);
353 354 355
}

void
356
RemoveAggregate(char *aggName, char *aggType)
357
{
358 359 360 361 362
	Relation	relation;
	HeapTuple	tup;
	char	   *userName;
	Oid			basetypeID = InvalidOid;
	bool		defined;
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378


	/*
	 * if a basetype is passed in, then attempt to find an aggregate for
	 * that specific type.
	 *
	 * else if the basetype is blank, then attempt to find an aggregate with
	 * a basetype of zero.	This is valid. It means that the aggregate is
	 * to apply to all basetypes.  ie, a counter of some sort.
	 *
	 */

	if (aggType)
	{
		basetypeID = TypeGet(aggType, &defined);
		if (!OidIsValid(basetypeID))
379
			elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
380 381 382
	}
	else
		basetypeID = 0;
383 384

#ifndef NO_SECURITY
385 386 387 388 389
	userName = GetPgUserName();
	if (!pg_aggr_ownercheck(userName, aggName, basetypeID))
	{
		if (aggType)
		{
390
			elog(ERROR, "RemoveAggregate: aggregate '%s' on type '%s': permission denied",
391 392 393 394
				 aggName, aggType);
		}
		else
		{
395
			elog(ERROR, "RemoveAggregate: aggregate '%s': permission denied",
396 397 398
				 aggName);
		}
	}
399
#endif
400

401
	relation = heap_openr(AggregateRelationName, RowExclusiveLock);
402
	tup = SearchSysCacheTuple(AGGNAME,
403 404 405
							  PointerGetDatum(aggName),
							  ObjectIdGetDatum(basetypeID),
							  0, 0);
406

407 408
	if (!HeapTupleIsValid(tup))
	{
409
		heap_close(relation, RowExclusiveLock);
410 411
		if (aggType)
		{
412
			elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
413 414 415 416
				 aggName, aggType);
		}
		else
		{
417
			elog(ERROR, "RemoveAggregate: aggregate '%s' for all types does not exist",
418 419 420
				 aggName);
		}
	}
V
Vadim B. Mikheev 已提交
421
	heap_delete(relation, &tup->t_self, NULL);
422

423
	heap_close(relation, RowExclusiveLock);
424
}