remove.c 9.8 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.29 1998/09/01 04:27:57 momjian Exp $
11 12 13
 *
 *-------------------------------------------------------------------------
 */
B
Bruce Momjian 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#include "postgres.h"

#include "access/heapam.h"
#include "catalog/catname.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 "commands/defrem.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "storage/bufmgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/syscache.h"

M
Marc G. Fournier 已提交
32
#ifndef HAVE_MEMMOVE
33
#include <regex/utils.h>
M
Marc G. Fournier 已提交
34
#else
35
#include <string.h>
M
Marc G. Fournier 已提交
36
#endif
37 38 39

/*
 * RemoveOperator --
40
 *		Deletes an operator.
41 42
 *
 * Exceptions:
43 44 45 46
 *		BadArg if name is invalid.
 *		BadArg if type1 is invalid.
 *		"WARN" if operator nonexistent.
 *		...
47 48
 */
void
49 50 51
RemoveOperator(char *operatorName,		/* operator name */
			   char *typeName1, /* first type name */
			   char *typeName2) /* optional second type name */
52
{
53 54 55 56 57 58
	Relation	relation;
	HeapTuple	tup;
	Oid			typeId1 = InvalidOid;
	Oid			typeId2 = InvalidOid;
	bool		defined;
	char	   *userName;
59
	char		oprtype;
60

61 62 63 64 65
	if (typeName1)
	{
		typeId1 = TypeGet(typeName1, &defined);
		if (!OidIsValid(typeId1))
		{
66
			elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1);
67 68
			return;
		}
69
	}
70 71 72 73 74 75

	if (typeName2)
	{
		typeId2 = TypeGet(typeName2, &defined);
		if (!OidIsValid(typeId2))
		{
76
			elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2);
77 78
			return;
		}
79
	}
80

81 82 83 84 85 86 87 88
	if (OidIsValid(typeId1) && OidIsValid(typeId2))
		oprtype = 'b';
	else if (OidIsValid(typeId1))
		oprtype = 'l';
	else
		oprtype = 'r';

	tup = SearchSysCacheTupleCopy(OPRNAME,
89 90 91 92 93
								  PointerGetDatum(operatorName),
								  ObjectIdGetDatum(typeId1),
								  ObjectIdGetDatum(typeId2),
								  CharGetDatum(oprtype));

94 95 96
	relation = heap_openr(OperatorRelationName);
	if (HeapTupleIsValid(tup))
	{
97
#ifndef NO_SECURITY
98 99 100 101
		userName = GetPgUserName();
		if (!pg_ownercheck(userName,
						   (char *) ObjectIdGetDatum(tup->t_oid),
						   OPROID))
102
			elog(ERROR, "RemoveOperator: operator '%s': permission denied",
103
				 operatorName);
104
#endif
105
		heap_delete(relation, &tup->t_ctid);
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
	pfree(tup);
130
	heap_close(relation);
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);
155 156 157
	for (i = 0; i < 3; ++i)
	{
		key[0].sk_attno = attnums[i];
158 159 160 161
		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
			heap_delete(rel, &tup->t_ctid);
		heap_endscan(scan);
162
	}
163
	heap_close(rel);
164 165 166
}

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

	/*
	 * 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],
195
						   0, 3, F_OIDEQ, (Datum) typeOid);
196 197 198 199

	oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
	oidptr->next = NULL;
	optr = oidptr;
200 201 202
	rel = heap_openr(AttributeRelationName);
	scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
	while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
203
	{
204
		optr->reloid = ((Form_pg_attribute) GETSTRUCT(tup))->attrelid;
205 206
		optr->next = (struct oidlist *) palloc(sizeof(*oidptr));
		optr = optr->next;
207
	}
208
	optr->next = NULL;
209 210
	heap_endscan(scan);
	heap_close(rel);
211 212 213 214


	ScanKeyEntryInitialize(&key[0], 0,
						   ObjectIdAttributeNumber,
B
Bruce Momjian 已提交
215
						   F_OIDEQ, (Datum) 0);
216
	optr = oidptr;
217
	rel = heap_openr(RelationRelationName);
218 219 220
	while (PointerIsValid((char *) optr->next))
	{
		key[0].sk_argument = (Datum) (optr++)->reloid;
221 222 223
		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
		tup = heap_getnext(scan, 0);
		if (HeapTupleIsValid(tup))
224
		{
225
			char	   *name;
226 227

			name = (((Form_pg_class) GETSTRUCT(tup))->relname).data;
228
			heap_destroy_with_catalog(name);
229 230
		}
	}
231 232
	heap_endscan(scan);
	heap_close(rel);
233
}
234

235
#endif	 /* NOTYET */
236 237

/*
238 239 240
 *	TypeRemove
 *		Removes the type 'typeName' and all attributes and relations that
 *		use it.
241 242
 */
void
243
RemoveType(char *typeName)		/* type name to be removed */
244
{
245 246 247 248 249
	Relation	relation;
	HeapTuple	tup;
	Oid			typeOid;
	char	   *shadow_type;
	char	   *userName;
250

251
#ifndef NO_SECURITY
252 253
	userName = GetPgUserName();
	if (!pg_ownercheck(userName, typeName, TYPNAME))
254
		elog(ERROR, "RemoveType: type '%s': permission denied",
255
			 typeName);
256
#endif
257 258

	relation = heap_openr(TypeRelationName);
259
	tup = SearchSysCacheTuple(TYPNAME,
260 261
							  PointerGetDatum(typeName),
							  0, 0, 0);
262 263 264 265

	if (!HeapTupleIsValid(tup))
	{
		heap_close(relation);
266
		elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
267
	}
268

269
	relation = heap_openr(TypeRelationName);
270
	typeOid = tup->t_oid;
271
	heap_delete(relation, &tup->t_ctid);
272 273 274

	/* Now, Delete the "array of" that type */
	shadow_type = makeArrayTypeName(typeName);
275
	tup = SearchSysCacheTuple(TYPNAME,
276 277
							  PointerGetDatum(shadow_type),
							  0, 0, 0);
278
	if (!HeapTupleIsValid(tup))
279
	{
280 281
		heap_close(relation);
		elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
282
	}
283

284
	typeOid = tup->t_oid;
285
	heap_delete(relation, &tup->t_ctid);
286 287

	heap_close(relation);
288 289 290 291
}

/*
 * RemoveFunction --
292
 *		Deletes a function.
293 294
 *
 * Exceptions:
295 296 297
 *		BadArg if name is invalid.
 *		"WARN" if function nonexistent.
 *		...
298 299
 */
void
300 301
RemoveFunction(char *functionName,		/* function name to be removed */
			   int nargs,
302
			   List *argNameList /* list of TypeNames */ )
303
{
304 305 306 307 308 309
	Relation	relation;
	HeapTuple	tup;
	Oid			argList[8];
	char	   *userName;
	char	   *typename;
	int			i;
310

311

B
Bruce Momjian 已提交
312
	MemSet(argList, 0, 8 * sizeof(Oid));
313 314 315 316 317 318 319 320 321
	for (i = 0; i < nargs; i++)
	{
		typename = strVal(lfirst(argNameList));
		argNameList = lnext(argNameList);

		if (strcmp(typename, "opaque") == 0)
			argList[i] = 0;
		else
		{
322 323
			tup = SearchSysCacheTuple(TYPNAME,
									  PointerGetDatum(typename),
324 325 326
									  0, 0, 0);

			if (!HeapTupleIsValid(tup))
327
				elog(ERROR, "RemoveFunction: type '%s' not found", typename);
328 329
			argList[i] = tup->t_oid;
		}
330
	}
331

332
#ifndef NO_SECURITY
333 334 335
	userName = GetPgUserName();
	if (!pg_func_ownercheck(userName, functionName, nargs, argList))
	{
336
		elog(ERROR, "RemoveFunction: function '%s': permission denied",
337
			 functionName);
338
	}
339 340 341
#endif

	relation = heap_openr(ProcedureRelationName);
342
	tup = SearchSysCacheTuple(PRONAME,
343 344 345 346
							  PointerGetDatum(functionName),
							  Int32GetDatum(nargs),
							  PointerGetDatum(argList),
							  0);
347

348
	if (!HeapTupleIsValid(tup))
349 350
	{
		heap_close(relation);
351
		func_error("RemoveFunction", functionName, nargs, argList, NULL);
352
	}
353

354 355
	if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
	{
356 357
		heap_close(relation);
		elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
358
	}
359

360
	heap_delete(relation, &tup->t_ctid);
361 362

	heap_close(relation);
363 364 365
}

void
366
RemoveAggregate(char *aggName, char *aggType)
367
{
368 369 370 371 372
	Relation	relation;
	HeapTuple	tup;
	char	   *userName;
	Oid			basetypeID = InvalidOid;
	bool		defined;
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388


	/*
	 * 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))
389
			elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
390 391 392
	}
	else
		basetypeID = 0;
393 394

#ifndef NO_SECURITY
395 396 397 398 399
	userName = GetPgUserName();
	if (!pg_aggr_ownercheck(userName, aggName, basetypeID))
	{
		if (aggType)
		{
400
			elog(ERROR, "RemoveAggregate: aggregate '%s' on type '%s': permission denied",
401 402 403 404
				 aggName, aggType);
		}
		else
		{
405
			elog(ERROR, "RemoveAggregate: aggregate '%s': permission denied",
406 407 408
				 aggName);
		}
	}
409
#endif
410 411

	relation = heap_openr(AggregateRelationName);
412
	tup = SearchSysCacheTuple(AGGNAME,
413 414 415
							  PointerGetDatum(aggName),
							  ObjectIdGetDatum(basetypeID),
							  0, 0);
416

417 418 419 420 421
	if (!HeapTupleIsValid(tup))
	{
		heap_close(relation);
		if (aggType)
		{
422
			elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
423 424 425 426
				 aggName, aggType);
		}
		else
		{
427
			elog(ERROR, "RemoveAggregate: aggregate '%s' for all types does not exist",
428 429 430
				 aggName);
		}
	}
431 432
	heap_delete(relation, &tup->t_ctid);

433
	heap_close(relation);
434
}