remove.c 10.8 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * remove.c
4
 *	  POSTGRES remove (function | type | operator ) utilty code.
5
 *
B
Add:  
Bruce Momjian 已提交
6 7
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.50 2000/07/04 06:11:29 tgl Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
B
Bruce Momjian 已提交
15 16 17 18 19 20 21
#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"
B
Hello.  
Bruce Momjian 已提交
22
#include "commands/comment.h"
B
Bruce Momjian 已提交
23 24 25 26 27 28
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/syscache.h"

29 30

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

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

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

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

80 81
	relation = heap_openr(OperatorRelationName, RowExclusiveLock);

82
	tup = SearchSysCacheTupleCopy(OPERNAME,
83 84 85 86 87
								  PointerGetDatum(operatorName),
								  ObjectIdGetDatum(typeId1),
								  ObjectIdGetDatum(typeId2),
								  CharGetDatum(oprtype));

88 89
	if (HeapTupleIsValid(tup))
	{
90
#ifndef NO_SECURITY
91 92
		userName = GetPgUserName();
		if (!pg_ownercheck(userName,
93
						   (char *) ObjectIdGetDatum(tup->t_data->t_oid),
94
						   OPEROID))
95
			elog(ERROR, "RemoveOperator: operator '%s': permission denied",
96
				 operatorName);
97
#endif
B
Hello.  
Bruce Momjian 已提交
98 99 100 101 102 103


		/*** Delete any comments associated with this operator ***/

		DeleteComments(tup->t_data->t_oid);

V
Vadim B. Mikheev 已提交
104
		heap_delete(relation, &tup->t_self, NULL);
B
Hello.  
Bruce Momjian 已提交
105

106
	}
107 108 109 110
	else
	{
		if (OidIsValid(typeId1) && OidIsValid(typeId2))
		{
111
			elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
112 113 114 115 116 117
				 operatorName,
				 typeName1,
				 typeName2);
		}
		else if (OidIsValid(typeId1))
		{
118
			elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
119 120 121 122 123
				 operatorName,
				 typeName1);
		}
		else
		{
124
			elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
125 126 127 128
				 operatorName,
				 typeName2);
		}
	}
129
	heap_freetuple(tup);
130
	heap_close(relation, RowExclusiveLock);
131 132 133 134 135 136 137 138
}

#ifdef NOTYET
/*
 * this stuff is to support removing all reference to a type
 * don't use it  - pma 2/1/94
 */
/*
139 140
 *	SingleOpOperatorRemove
 *		Removes all operators that have operands or a result of type 'typeOid'.
141 142 143 144
 */
static void
SingleOpOperatorRemove(Oid typeOid)
{
145
	Relation	rel;
146
	ScanKeyData key[3];
147
	HeapScanDesc scan;
148 149
	HeapTuple	tup;
	static		attnums[3] = {7, 8, 9}; /* left, right, return */
150
	int			i;
151 152

	ScanKeyEntryInitialize(&key[0],
153
						   0, 0, F_OIDEQ, (Datum) typeOid);
154
	rel = heap_openr(OperatorRelationName, RowExclusiveLock);
155 156 157
	for (i = 0; i < 3; ++i)
	{
		key[0].sk_attno = attnums[i];
158
		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
159 160
		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
		{
B
Hello.  
Bruce Momjian 已提交
161

162 163
			/*** This is apparently a routine not in use, but remove ***/
			/*** any comments anyways ***/
B
Hello.  
Bruce Momjian 已提交
164

165
			DeleteComments(tup->t_data->t_oid);
B
Hello.  
Bruce Momjian 已提交
166

167
			heap_delete(rel, &tup->t_self, NULL);
168

B
Hello.  
Bruce Momjian 已提交
169 170
		}

171
		heap_endscan(scan);
172
	}
173
	heap_close(rel, RowExclusiveLock);
174 175 176
}

/*
177 178 179 180
 *	AttributeAndRelationRemove
 *		Removes all entries in the attribute and relation relations
 *		that contain entries of type 'typeOid'.
 *		Currently nothing calls this code, it is untested.
181 182 183 184
 */
static void
AttributeAndRelationRemove(Oid typeOid)
{
185 186
	struct oidlist
	{
187
		Oid			reloid;
188 189 190
		struct oidlist *next;
	};
	struct oidlist *oidptr,
191
			   *optr;
192
	Relation	rel;
193
	ScanKeyData key[1];
194
	HeapScanDesc scan;
195
	HeapTuple	tup;
196 197 198 199 200 201 202 203 204

	/*
	 * 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],
205
						   0, 3, F_OIDEQ, (Datum) typeOid);
206 207 208 209

	oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
	oidptr->next = NULL;
	optr = oidptr;
210
	rel = heap_openr(AttributeRelationName, AccessShareLock);
211 212
	scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
	while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
213
	{
214
		optr->reloid = ((Form_pg_attribute) GETSTRUCT(tup))->attrelid;
215 216
		optr->next = (struct oidlist *) palloc(sizeof(*oidptr));
		optr = optr->next;
217
	}
218
	optr->next = NULL;
219
	heap_endscan(scan);
220
	heap_close(rel, AccessShareLock);
221

222
	optr = oidptr;
223 224 225

	ScanKeyEntryInitialize(&key[0], 0,
						   ObjectIdAttributeNumber,
B
Bruce Momjian 已提交
226
						   F_OIDEQ, (Datum) 0);
227 228
	/* get RowExclusiveLock because heap_destroy will need it */
	rel = heap_openr(RelationRelationName, RowExclusiveLock);
229 230 231
	while (PointerIsValid((char *) optr->next))
	{
		key[0].sk_argument = (Datum) (optr++)->reloid;
232 233 234
		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
		tup = heap_getnext(scan, 0);
		if (HeapTupleIsValid(tup))
235
		{
236
			char	   *name;
237

238
			name = NameStr(((Form_pg_class) GETSTRUCT(tup))->relname);
239
			heap_drop_with_catalog(name, allowSystemTableMods);
240
		}
241
		heap_endscan(scan);
242
	}
243
	heap_close(rel, RowExclusiveLock);
244
}
245

246
#endif	 /* NOTYET */
247 248

/*
249 250 251
 *	TypeRemove
 *		Removes the type 'typeName' and all attributes and relations that
 *		use it.
252 253
 */
void
254
RemoveType(char *typeName)		/* type name to be removed */
255
{
256 257 258 259 260
	Relation	relation;
	HeapTuple	tup;
	Oid			typeOid;
	char	   *shadow_type;
	char	   *userName;
261

262
#ifndef NO_SECURITY
263
	userName = GetPgUserName();
264
	if (!pg_ownercheck(userName, typeName, TYPENAME))
265
		elog(ERROR, "RemoveType: type '%s': permission denied",
266
			 typeName);
267
#endif
268

269 270
	relation = heap_openr(TypeRelationName, RowExclusiveLock);

271
	tup = SearchSysCacheTuple(TYPENAME,
272 273
							  PointerGetDatum(typeName),
							  0, 0, 0);
274 275
	if (!HeapTupleIsValid(tup))
	{
276
		heap_close(relation, RowExclusiveLock);
277
		elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
278
	}
279

280
	typeOid = tup->t_data->t_oid;
B
Hello.  
Bruce Momjian 已提交
281 282 283 284 285

	/*** Delete any comments associated with this type ***/

	DeleteComments(typeOid);

V
Vadim B. Mikheev 已提交
286
	heap_delete(relation, &tup->t_self, NULL);
287 288 289

	/* Now, Delete the "array of" that type */
	shadow_type = makeArrayTypeName(typeName);
290
	tup = SearchSysCacheTuple(TYPENAME,
291 292
							  PointerGetDatum(shadow_type),
							  0, 0, 0);
293
	if (!HeapTupleIsValid(tup))
294
	{
295 296
		heap_close(relation, RowExclusiveLock);
		elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
297
	}
298

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

301
	heap_close(relation, RowExclusiveLock);
302 303 304
}

/*
B
Bruce Momjian 已提交
305
 * RemoveFunction
306
 *		Deletes a function.
307 308
 *
 * Exceptions:
309 310 311
 *		BadArg if name is invalid.
 *		"WARN" if function nonexistent.
 *		...
312 313
 */
void
314 315
RemoveFunction(char *functionName,		/* function name to be removed */
			   int nargs,
316
			   List *argNameList /* list of TypeNames */ )
317
{
318 319
	Relation	relation;
	HeapTuple	tup;
320
	Oid			argList[FUNC_MAX_ARGS];
321 322 323
	char	   *userName;
	char	   *typename;
	int			i;
324

325 326 327
	if (nargs > FUNC_MAX_ARGS)
		elog(ERROR, "functions cannot have more than %d arguments",
			 FUNC_MAX_ARGS);
328
	MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
329 330 331 332 333 334 335 336 337
	for (i = 0; i < nargs; i++)
	{
		typename = strVal(lfirst(argNameList));
		argNameList = lnext(argNameList);

		if (strcmp(typename, "opaque") == 0)
			argList[i] = 0;
		else
		{
338
			tup = SearchSysCacheTuple(TYPENAME,
339
									  PointerGetDatum(typename),
340 341 342
									  0, 0, 0);

			if (!HeapTupleIsValid(tup))
343
				elog(ERROR, "RemoveFunction: type '%s' not found", typename);
344
			argList[i] = tup->t_data->t_oid;
345
		}
346
	}
347

348
#ifndef NO_SECURITY
349 350 351
	userName = GetPgUserName();
	if (!pg_func_ownercheck(userName, functionName, nargs, argList))
	{
352
		elog(ERROR, "RemoveFunction: function '%s': permission denied",
353
			 functionName);
354
	}
355 356
#endif

357
	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
358
	tup = SearchSysCacheTuple(PROCNAME,
359 360 361 362
							  PointerGetDatum(functionName),
							  Int32GetDatum(nargs),
							  PointerGetDatum(argList),
							  0);
363

364
	if (!HeapTupleIsValid(tup))
365
	{
366
		heap_close(relation, RowExclusiveLock);
367
		func_error("RemoveFunction", functionName, nargs, argList, NULL);
368
	}
369

370 371
	if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId ||
		((Form_pg_proc) GETSTRUCT(tup))->prolang == NEWINTERNALlanguageId)
372
	{
373
		heap_close(relation, RowExclusiveLock);
374
		elog(NOTICE, "Removing built-in function \"%s\"", functionName);
375
	}
376

B
Hello.  
Bruce Momjian 已提交
377 378 379 380
	/*** Delete any comments associated with this function ***/

	DeleteComments(tup->t_data->t_oid);

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

383
	heap_close(relation, RowExclusiveLock);
384 385 386
}

void
387
RemoveAggregate(char *aggName, char *aggType)
388
{
389 390 391 392 393
	Relation	relation;
	HeapTuple	tup;
	char	   *userName;
	Oid			basetypeID = InvalidOid;
	bool		defined;
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409


	/*
	 * 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))
410
			elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
411 412 413
	}
	else
		basetypeID = 0;
414 415

#ifndef NO_SECURITY
416 417 418 419 420
	userName = GetPgUserName();
	if (!pg_aggr_ownercheck(userName, aggName, basetypeID))
	{
		if (aggType)
		{
421
			elog(ERROR, "RemoveAggregate: aggregate '%s' on type '%s': permission denied",
422 423 424 425
				 aggName, aggType);
		}
		else
		{
426
			elog(ERROR, "RemoveAggregate: aggregate '%s': permission denied",
427 428 429
				 aggName);
		}
	}
430
#endif
431

432
	relation = heap_openr(AggregateRelationName, RowExclusiveLock);
433
	tup = SearchSysCacheTuple(AGGNAME,
434 435 436
							  PointerGetDatum(aggName),
							  ObjectIdGetDatum(basetypeID),
							  0, 0);
437

438 439
	if (!HeapTupleIsValid(tup))
	{
440
		heap_close(relation, RowExclusiveLock);
441 442
		if (aggType)
		{
443
			elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
444 445 446 447
				 aggName, aggType);
		}
		else
		{
448
			elog(ERROR, "RemoveAggregate: aggregate '%s' for all types does not exist",
449 450 451
				 aggName);
		}
	}
452

B
Hello.  
Bruce Momjian 已提交
453 454 455 456
	/*** Remove any comments related to this aggregate ***/

	DeleteComments(tup->t_data->t_oid);

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

459
	heap_close(relation, RowExclusiveLock);
460
}