remove.c 10.5 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.39 1999/11/07 23:08:02 momjian Exp $
11 12 13
 *
 *-------------------------------------------------------------------------
 */
B
Bruce Momjian 已提交
14 15 16 17 18 19 20
#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 已提交
21
#include "commands/comment.h"
B
Bruce Momjian 已提交
22 23 24 25 26 27
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/syscache.h"

28 29

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

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

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

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

79 80
	relation = heap_openr(OperatorRelationName, RowExclusiveLock);

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

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


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

		DeleteComments(tup->t_data->t_oid);

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

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

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

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

		  /*** This is apparently a routine not in use, but remove ***/
		  /*** any comments anyways ***/

		  DeleteComments(tup->t_data->t_oid);

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

169
		heap_endscan(scan);
170
	}
171
	heap_close(rel, RowExclusiveLock);
172 173 174
}

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

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

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

220
	optr = oidptr;
221 222 223

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

236
			name = NameStr(((Form_pg_class) GETSTRUCT(tup))->relname);
237
			heap_destroy_with_catalog(name);
238
		}
239
		heap_endscan(scan);
240
	}
241
	heap_close(rel, RowExclusiveLock);
242
}
243

244
#endif	 /* NOTYET */
245 246

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

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

267 268
	relation = heap_openr(TypeRelationName, RowExclusiveLock);

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

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

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

	DeleteComments(typeOid);

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

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

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

299
	heap_close(relation, RowExclusiveLock);
300 301 302
}

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

323

B
Bruce Momjian 已提交
324
	MemSet(argList, 0, 8 * sizeof(Oid));
325 326 327 328 329 330 331 332 333
	for (i = 0; i < nargs; i++)
	{
		typename = strVal(lfirst(argNameList));
		argNameList = lnext(argNameList);

		if (strcmp(typename, "opaque") == 0)
			argList[i] = 0;
		else
		{
334 335
			tup = SearchSysCacheTuple(TYPNAME,
									  PointerGetDatum(typename),
336 337 338
									  0, 0, 0);

			if (!HeapTupleIsValid(tup))
339
				elog(ERROR, "RemoveFunction: type '%s' not found", typename);
340
			argList[i] = tup->t_data->t_oid;
341
		}
342
	}
343

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

353
	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
354
	tup = SearchSysCacheTuple(PRONAME,
355 356 357 358
							  PointerGetDatum(functionName),
							  Int32GetDatum(nargs),
							  PointerGetDatum(argList),
							  0);
359

360
	if (!HeapTupleIsValid(tup))
361
	{
362
		heap_close(relation, RowExclusiveLock);
363
		func_error("RemoveFunction", functionName, nargs, argList, NULL);
364
	}
365

366 367
	if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
	{
368
		heap_close(relation, RowExclusiveLock);
369
		elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
370
	}
371

B
Hello.  
Bruce Momjian 已提交
372 373 374 375
	/*** Delete any comments associated with this function ***/

	DeleteComments(tup->t_data->t_oid);

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

378
	heap_close(relation, RowExclusiveLock);
379 380 381
}

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


	/*
	 * 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))
405
			elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
406 407 408
	}
	else
		basetypeID = 0;
409 410

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

427
	relation = heap_openr(AggregateRelationName, RowExclusiveLock);
428
	tup = SearchSysCacheTuple(AGGNAME,
429 430 431
							  PointerGetDatum(aggName),
							  ObjectIdGetDatum(basetypeID),
							  0, 0);
432

433 434
	if (!HeapTupleIsValid(tup))
	{
435
		heap_close(relation, RowExclusiveLock);
436 437
		if (aggType)
		{
438
			elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
439 440 441 442
				 aggName, aggType);
		}
		else
		{
443
			elog(ERROR, "RemoveAggregate: aggregate '%s' for all types does not exist",
444 445 446
				 aggName);
		}
	}
B
Hello.  
Bruce Momjian 已提交
447 448 449 450 451
	
	/*** Remove any comments related to this aggregate ***/

	DeleteComments(tup->t_data->t_oid);

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

454
	heap_close(relation, RowExclusiveLock);
455
}