lsyscache.c 32.4 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * lsyscache.c
4
 *	  Convenience routines for common queries in the system catalog cache.
5
 *
Bruce Momjian's avatar
Bruce Momjian committed
6
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9
 *
 * IDENTIFICATION
10
 *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.88 2002/12/05 04:04:44 momjian Exp $
11 12
 *
 * NOTES
13
 *	  Eventually, the index information should go through here, too.
14 15 16
 *-------------------------------------------------------------------------
 */
#include "postgres.h"
17
#include "miscadmin.h"
18

19
#include "access/tupmacs.h"
20
#include "catalog/pg_amop.h"
21
#include "catalog/pg_namespace.h"
22
#include "catalog/pg_opclass.h"
Bruce Momjian's avatar
Bruce Momjian committed
23
#include "catalog/pg_operator.h"
24
#include "catalog/pg_proc.h"
25
#include "catalog/pg_shadow.h"
26
#include "catalog/pg_statistic.h"
27
#include "catalog/pg_type.h"
Tom Lane's avatar
Tom Lane committed
28
#include "nodes/makefuncs.h"
29 30
#include "utils/array.h"
#include "utils/builtins.h"
Bruce Momjian's avatar
Bruce Momjian committed
31 32
#include "utils/lsyscache.h"
#include "utils/syscache.h"
33

34

35
/*				---------- AMOP CACHES ----------						 */
36

37
/*
38
 * op_in_opclass
39
 *
40
 *		Return t iff operator 'opno' is in operator class 'opclass'.
41 42
 */
bool
43
op_in_opclass(Oid opno, Oid opclass)
44
{
45 46 47
	return SearchSysCacheExists(AMOPOPID,
								ObjectIdGetDatum(opclass),
								ObjectIdGetDatum(opno),
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
								0, 0);
}

/*
 * op_requires_recheck
 *
 *		Return t if operator 'opno' requires a recheck when used as a
 *		member of opclass 'opclass' (ie, this opclass is lossy for this
 *		operator).
 *
 * Caller should already have verified that opno is a member of opclass,
 * therefore we raise an error if the tuple is not found.
 */
bool
op_requires_recheck(Oid opno, Oid opclass)
{
	HeapTuple	tp;
	Form_pg_amop amop_tup;
	bool		result;

	tp = SearchSysCache(AMOPOPID,
						ObjectIdGetDatum(opclass),
						ObjectIdGetDatum(opno),
						0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u",
			 opno, opclass);
	amop_tup = (Form_pg_amop) GETSTRUCT(tp);

	result = amop_tup->amopreqcheck;
	ReleaseSysCache(tp);
	return result;
80 81
}

82
/*				---------- ATTRIBUTE CACHES ----------					 */
83

84
/*
85
 * get_attname
86 87 88
 *
 *		Given the relation id and the attribute number,
 *		return the "attname" field from the attribute relation.
89 90
 *
 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
91
 */
92
char *
93 94
get_attname(Oid relid, AttrNumber attnum)
{
95
	HeapTuple	tp;
96

97 98 99 100
	tp = SearchSysCache(ATTNUM,
						ObjectIdGetDatum(relid),
						Int16GetDatum(attnum),
						0, 0);
101 102 103
	if (HeapTupleIsValid(tp))
	{
		Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
104
		char	   *result;
105

106 107 108
		result = pstrdup(NameStr(att_tup->attname));
		ReleaseSysCache(tp);
		return result;
109
	}
110
	else
Bruce Momjian's avatar
Bruce Momjian committed
111
		return NULL;
112 113
}

114
/*
115
 * get_attnum
116 117 118
 *
 *		Given the relation id and the attribute name,
 *		return the "attnum" field from the attribute relation.
119 120
 *
 *		Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
121 122
 */
AttrNumber
123
get_attnum(Oid relid, const char *attname)
124
{
125
	HeapTuple	tp;
126

127
	tp = SearchSysCacheAttName(relid, attname);
128 129 130
	if (HeapTupleIsValid(tp))
	{
		Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
131
		AttrNumber	result;
132

133 134 135
		result = att_tup->attnum;
		ReleaseSysCache(tp);
		return result;
136
	}
137
	else
Bruce Momjian's avatar
Bruce Momjian committed
138
		return InvalidAttrNumber;
139 140
}

141
/*
142
 * get_atttype
143 144 145
 *
 *		Given the relation OID and the attribute number with the relation,
 *		return the attribute type OID.
146 147 148 149
 */
Oid
get_atttype(Oid relid, AttrNumber attnum)
{
150
	HeapTuple	tp;
151

152 153 154 155
	tp = SearchSysCache(ATTNUM,
						ObjectIdGetDatum(relid),
						Int16GetDatum(attnum),
						0, 0);
156 157 158
	if (HeapTupleIsValid(tp))
	{
		Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
159
		Oid			result;
160

161 162 163
		result = att_tup->atttypid;
		ReleaseSysCache(tp);
		return result;
164
	}
165
	else
166
		return InvalidOid;
167 168
}

Bruce Momjian's avatar
Bruce Momjian committed
169
/*
170
 * get_atttypmod
Bruce Momjian's avatar
Bruce Momjian committed
171 172 173 174
 *
 *		Given the relation id and the attribute number,
 *		return the "atttypmod" field from the attribute relation.
 */
175
int32
Bruce Momjian's avatar
Bruce Momjian committed
176 177
get_atttypmod(Oid relid, AttrNumber attnum)
{
178
	HeapTuple	tp;
Bruce Momjian's avatar
Bruce Momjian committed
179

180 181 182 183
	tp = SearchSysCache(ATTNUM,
						ObjectIdGetDatum(relid),
						Int16GetDatum(attnum),
						0, 0);
184 185 186
	if (HeapTupleIsValid(tp))
	{
		Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
187
		int32		result;
188

189 190 191
		result = att_tup->atttypmod;
		ReleaseSysCache(tp);
		return result;
192
	}
Bruce Momjian's avatar
Bruce Momjian committed
193
	else
194
		return -1;
Bruce Momjian's avatar
Bruce Momjian committed
195 196
}

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
/*
 * get_atttypetypmod
 *
 *		A two-fer: given the relation id and the attribute number,
 *		fetch both type OID and atttypmod in a single cache lookup.
 *
 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
 * raises an error if it can't obtain the information.
 */
void
get_atttypetypmod(Oid relid, AttrNumber attnum,
				  Oid *typid, int32 *typmod)
{
	HeapTuple	tp;
	Form_pg_attribute att_tup;

	tp = SearchSysCache(ATTNUM,
						ObjectIdGetDatum(relid),
						Int16GetDatum(attnum),
						0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "cache lookup failed for relation %u attribute %d",
			 relid, attnum);
	att_tup = (Form_pg_attribute) GETSTRUCT(tp);

	*typid = att_tup->atttypid;
	*typmod = att_tup->atttypmod;
	ReleaseSysCache(tp);
}

227
/*				---------- INDEX CACHE ----------						 */
228

229
/*		watch this space...
230 231
 */

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
/*				---------- OPCLASS CACHE ----------						 */

/*
 * opclass_is_btree
 *
 *		Returns TRUE iff the specified opclass is associated with the
 *		btree index access method.
 */
bool
opclass_is_btree(Oid opclass)
{
	HeapTuple	tp;
	Form_pg_opclass cla_tup;
	bool		result;

	tp = SearchSysCache(CLAOID,
						ObjectIdGetDatum(opclass),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "cache lookup failed for opclass %u", opclass);
	cla_tup = (Form_pg_opclass) GETSTRUCT(tp);

	result = (cla_tup->opcamid == BTREE_AM_OID);
	ReleaseSysCache(tp);
	return result;
}

259
/*				---------- OPERATOR CACHE ----------					 */
260

261
/*
262
 * get_opcode
263 264
 *
 *		Returns the regproc id of the routine used to implement an
265
 *		operator given the operator oid.
266 267 268 269
 */
RegProcedure
get_opcode(Oid opno)
{
270
	HeapTuple	tp;
271

272 273 274
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
275 276 277
	if (HeapTupleIsValid(tp))
	{
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
278
		RegProcedure result;
279

280 281 282
		result = optup->oprcode;
		ReleaseSysCache(tp);
		return result;
283
	}
284
	else
285
		return (RegProcedure) InvalidOid;
286 287 288
}

/*
289
 * get_opname
290
 *	  returns the name of the operator with the given opno
291
 *
292
 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
293
 */
294
char *
295 296
get_opname(Oid opno)
{
297
	HeapTuple	tp;
298

299 300 301
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
302
	if (HeapTupleIsValid(tp))
303
	{
304
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
305
		char	   *result;
306

307 308 309
		result = pstrdup(NameStr(optup->oprname));
		ReleaseSysCache(tp);
		return result;
310
	}
311 312
	else
		return NULL;
313 314
}

315
/*
316
 * op_mergejoinable
317 318
 *
 *		Returns the left and right sort operators and types corresponding to a
319
 *		mergejoinable operator, or nil if the operator is not mergejoinable.
320 321
 */
bool
322
op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
323
{
324
	HeapTuple	tp;
325
	bool		result = false;
326

327 328 329
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
330
	if (HeapTupleIsValid(tp))
331
	{
332 333 334 335 336 337 338
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);

		if (optup->oprlsortop &&
			optup->oprrsortop &&
			optup->oprleft == ltype &&
			optup->oprright == rtype)
		{
339 340
			*leftOp = optup->oprlsortop;
			*rightOp = optup->oprrsortop;
341
			result = true;
342
		}
343
		ReleaseSysCache(tp);
344
	}
345
	return result;
346 347
}

348 349 350 351 352
/*
 * op_mergejoin_crossops
 *
 *		Returns the cross-type comparison operators (ltype "<" rtype and
 *		ltype ">" rtype) for an operator previously determined to be
Bruce Momjian's avatar
Bruce Momjian committed
353
 *		mergejoinable.	Optionally, fetches the regproc ids of these
354 355 356 357 358 359 360 361 362 363
 *		operators, as well as their operator OIDs.
 */
void
op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
					  RegProcedure *ltproc, RegProcedure *gtproc)
{
	HeapTuple	tp;
	Form_pg_operator optup;

	/*
364
	 * Get the declared comparison operators of the operator.
365 366 367 368 369 370 371
	 */
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))	/* shouldn't happen */
		elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
	optup = (Form_pg_operator) GETSTRUCT(tp);
372 373
	*ltop = optup->oprltcmpop;
	*gtop = optup->oprgtcmpop;
374 375
	ReleaseSysCache(tp);

376 377
	/* Check < op provided */
	if (!OidIsValid(*ltop))
378 379 380
		elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
			 opno);
	if (ltproc)
381
		*ltproc = get_opcode(*ltop);
382

383 384
	/* Check > op provided */
	if (!OidIsValid(*gtop))
385 386 387
		elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
			 opno);
	if (gtproc)
388
		*gtproc = get_opcode(*gtop);
389 390
}

391
/*
392
 * op_hashjoinable
393 394
 *
 * Returns the hash operator corresponding to a hashjoinable operator,
395
 * or InvalidOid if the operator is not hashjoinable.
396 397 398 399
 */
Oid
op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
{
400
	HeapTuple	tp;
401
	Oid			result = InvalidOid;
402

403 404 405
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
406 407 408 409 410 411 412
	if (HeapTupleIsValid(tp))
	{
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);

		if (optup->oprcanhash &&
			optup->oprleft == ltype &&
			optup->oprright == rtype)
413 414
			result = opno;
		ReleaseSysCache(tp);
415
	}
416
	return result;
417 418
}

419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
/*
 * op_strict
 *
 * Get the proisstrict flag for the operator's underlying function.
 */
bool
op_strict(Oid opno)
{
	RegProcedure funcid = get_opcode(opno);

	if (funcid == (RegProcedure) InvalidOid)
		elog(ERROR, "Operator OID %u does not exist", opno);

	return func_strict((Oid) funcid);
}

435
/*
436
 * op_volatile
437
 *
438
 * Get the provolatile flag for the operator's underlying function.
439
 */
440 441
char
op_volatile(Oid opno)
442
{
443
	RegProcedure funcid = get_opcode(opno);
444 445 446 447

	if (funcid == (RegProcedure) InvalidOid)
		elog(ERROR, "Operator OID %u does not exist", opno);

448
	return func_volatile((Oid) funcid);
449 450
}

451
/*
452
 * get_commutator
453 454
 *
 *		Returns the corresponding commutator of an operator.
455 456 457 458
 */
Oid
get_commutator(Oid opno)
{
459
	HeapTuple	tp;
460

461 462 463
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
464 465 466
	if (HeapTupleIsValid(tp))
	{
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
467
		Oid			result;
468

469 470 471
		result = optup->oprcom;
		ReleaseSysCache(tp);
		return result;
472
	}
473
	else
474
		return InvalidOid;
475 476
}

477
/*
478
 * get_negator
479 480
 *
 *		Returns the corresponding negator of an operator.
481 482 483 484
 */
Oid
get_negator(Oid opno)
{
485
	HeapTuple	tp;
486

487 488 489
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
490 491 492
	if (HeapTupleIsValid(tp))
	{
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
493
		Oid			result;
494

495 496 497
		result = optup->oprnegate;
		ReleaseSysCache(tp);
		return result;
498
	}
499
	else
500
		return InvalidOid;
501 502
}

503
/*
504
 * get_oprrest
505 506
 *
 *		Returns procedure id for computing selectivity of an operator.
507 508 509 510
 */
RegProcedure
get_oprrest(Oid opno)
{
511
	HeapTuple	tp;
512

513 514 515
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
516 517 518
	if (HeapTupleIsValid(tp))
	{
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
519
		RegProcedure result;
520

521 522 523
		result = optup->oprrest;
		ReleaseSysCache(tp);
		return result;
524
	}
525
	else
526
		return (RegProcedure) InvalidOid;
527 528
}

529
/*
530
 * get_oprjoin
531 532
 *
 *		Returns procedure id for computing selectivity of a join.
533 534 535 536
 */
RegProcedure
get_oprjoin(Oid opno)
{
537
	HeapTuple	tp;
538

539 540 541
	tp = SearchSysCache(OPEROID,
						ObjectIdGetDatum(opno),
						0, 0, 0);
542 543 544
	if (HeapTupleIsValid(tp))
	{
		Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
545
		RegProcedure result;
546

547 548 549
		result = optup->oprjoin;
		ReleaseSysCache(tp);
		return result;
550
	}
551
	else
552
		return (RegProcedure) InvalidOid;
553 554
}

555 556
/*				---------- FUNCTION CACHE ----------					 */

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
/*
 * get_func_name
 *	  returns the name of the function with the given funcid
 *
 * Note: returns a palloc'd copy of the string, or NULL if no such function.
 */
char *
get_func_name(Oid funcid)
{
	HeapTuple	tp;

	tp = SearchSysCache(PROCOID,
						ObjectIdGetDatum(funcid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
		char	   *result;

		result = pstrdup(NameStr(functup->proname));
		ReleaseSysCache(tp);
		return result;
	}
	else
		return NULL;
}

584 585 586 587 588 589 590
/*
 * get_func_rettype
 *		Given procedure id, return the function's result type.
 */
Oid
get_func_rettype(Oid funcid)
{
591 592
	HeapTuple	tp;
	Oid			result;
593

594 595 596 597
	tp = SearchSysCache(PROCOID,
						ObjectIdGetDatum(funcid),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
598 599
		elog(ERROR, "Function OID %u does not exist", funcid);

600 601 602
	result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
	ReleaseSysCache(tp);
	return result;
603 604
}

605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
/*
 * get_func_retset
 *		Given procedure id, return the function's proretset flag.
 */
bool
get_func_retset(Oid funcid)
{
	HeapTuple	tp;
	bool		result;

	tp = SearchSysCache(PROCOID,
						ObjectIdGetDatum(funcid),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "Function OID %u does not exist", funcid);

	result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
	ReleaseSysCache(tp);
	return result;
}

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
/*
 * func_strict
 *		Given procedure id, return the function's proisstrict flag.
 */
bool
func_strict(Oid funcid)
{
	HeapTuple	tp;
	bool		result;

	tp = SearchSysCache(PROCOID,
						ObjectIdGetDatum(funcid),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "Function OID %u does not exist", funcid);

	result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
	ReleaseSysCache(tp);
	return result;
}

647
/*
648 649
 * func_volatile
 *		Given procedure id, return the function's provolatile flag.
650
 */
651 652
char
func_volatile(Oid funcid)
653
{
654
	HeapTuple	tp;
655
	char		result;
656

657 658 659 660
	tp = SearchSysCache(PROCOID,
						ObjectIdGetDatum(funcid),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
661 662
		elog(ERROR, "Function OID %u does not exist", funcid);

663
	result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
664 665
	ReleaseSysCache(tp);
	return result;
666 667
}

668
/*				---------- RELATION CACHE ----------					 */
669

670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
/*
 * get_relname_relid
 *		Given name and namespace of a relation, look up the OID.
 *
 * Returns InvalidOid if there is no such relation.
 */
Oid
get_relname_relid(const char *relname, Oid relnamespace)
{
	return GetSysCacheOid(RELNAMENSP,
						  PointerGetDatum(relname),
						  ObjectIdGetDatum(relnamespace),
						  0, 0);
}

685 686 687 688 689 690 691
/*
 * get_system_catalog_relid
 *		Get the OID of a system catalog identified by name.
 */
Oid
get_system_catalog_relid(const char *catname)
{
Bruce Momjian's avatar
Bruce Momjian committed
692
	Oid			relid;
693 694 695 696 697 698 699 700 701 702 703

	relid = GetSysCacheOid(RELNAMENSP,
						   PointerGetDatum(catname),
						   ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
						   0, 0);
	if (!OidIsValid(relid))
		elog(ERROR, "get_system_catalog_relid: cannot find %s", catname);

	return relid;
}

704
#ifdef NOT_USED
705
/*
706
 * get_relnatts
707 708
 *
 *		Returns the number of attributes for a given relation.
709 710 711 712
 */
int
get_relnatts(Oid relid)
{
713
	HeapTuple	tp;
714

715 716 717
	tp = SearchSysCache(RELOID,
						ObjectIdGetDatum(relid),
						0, 0, 0);
718 719 720
	if (HeapTupleIsValid(tp))
	{
		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
721
		int			result;
722

723 724 725
		result = reltup->relnatts;
		ReleaseSysCache(tp);
		return result;
726
	}
727
	else
Bruce Momjian's avatar
Bruce Momjian committed
728
		return InvalidAttrNumber;
729
}
730
#endif
731

732
/*
733
 * get_rel_name
734
 *		Returns the name of a given relation.
735
 *
736 737 738 739
 * Returns a palloc'd copy of the string, or NULL if no such relation.
 *
 * NOTE: since relation name is not unique, be wary of code that uses this
 * for anything except preparing error messages.
740
 */
741
char *
742 743
get_rel_name(Oid relid)
{
744
	HeapTuple	tp;
745

746 747 748
	tp = SearchSysCache(RELOID,
						ObjectIdGetDatum(relid),
						0, 0, 0);
749 750 751
	if (HeapTupleIsValid(tp))
	{
		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
752
		char	   *result;
753

754 755 756
		result = pstrdup(NameStr(reltup->relname));
		ReleaseSysCache(tp);
		return result;
757
	}
758
	else
Bruce Momjian's avatar
Bruce Momjian committed
759
		return NULL;
760 761
}

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
/*
 * get_rel_namespace
 *
 *		Returns the pg_namespace OID associated with a given relation.
 */
Oid
get_rel_namespace(Oid relid)
{
	HeapTuple	tp;

	tp = SearchSysCache(RELOID,
						ObjectIdGetDatum(relid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
Bruce Momjian's avatar
Bruce Momjian committed
778
		Oid			result;
779 780 781 782 783 784 785 786 787

		result = reltup->relnamespace;
		ReleaseSysCache(tp);
		return result;
	}
	else
		return InvalidOid;
}

788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
/*
 * get_rel_type_id
 *
 *		Returns the pg_type OID associated with a given relation.
 *
 * Note: not all pg_class entries have associated pg_type OIDs; so be
 * careful to check for InvalidOid result.
 */
Oid
get_rel_type_id(Oid relid)
{
	HeapTuple	tp;

	tp = SearchSysCache(RELOID,
						ObjectIdGetDatum(relid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
Bruce Momjian's avatar
Bruce Momjian committed
807
		Oid			result;
808 809 810 811 812 813 814 815 816

		result = reltup->reltype;
		ReleaseSysCache(tp);
		return result;
	}
	else
		return InvalidOid;
}

817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
/*
 * get_rel_relkind
 *
 *		Returns the relkind associated with a given relation.
 */
char
get_rel_relkind(Oid relid)
{
	HeapTuple	tp;

	tp = SearchSysCache(RELOID,
						ObjectIdGetDatum(relid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
		char		result;

		result = reltup->relkind;
		ReleaseSysCache(tp);
		return result;
	}
	else
		return '\0';
}


844
/*				---------- TYPE CACHE ----------						 */
845

846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
/*
 * get_typisdefined
 *
 *		Given the type OID, determine whether the type is defined
 *		(if not, it's only a shell).
 */
bool
get_typisdefined(Oid typid)
{
	HeapTuple	tp;

	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
		bool		result;

		result = typtup->typisdefined;
		ReleaseSysCache(tp);
		return result;
	}
	else
		return false;
}

873
/*
874
 * get_typlen
875 876
 *
 *		Given the type OID, return the length of the type.
877 878 879 880
 */
int16
get_typlen(Oid typid)
{
881
	HeapTuple	tp;
882

883 884 885
	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
886 887 888
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
889
		int16		result;
890

891 892 893
		result = typtup->typlen;
		ReleaseSysCache(tp);
		return result;
894
	}
895
	else
896
		return 0;
897 898
}

899
/*
900
 * get_typbyval
901 902
 *
 *		Given the type OID, determine whether the type is returned by value or
903
 *		not.  Returns true if by value, false if by reference.
904 905 906 907
 */
bool
get_typbyval(Oid typid)
{
908
	HeapTuple	tp;
909

910 911 912
	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
913 914 915
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
916
		bool		result;
917

918 919 920
		result = typtup->typbyval;
		ReleaseSysCache(tp);
		return result;
921
	}
922
	else
Bruce Momjian's avatar
Bruce Momjian committed
923
		return false;
924 925
}

926 927 928 929 930 931
/*
 * get_typlenbyval
 *
 *		A two-fer: given the type OID, return both typlen and typbyval.
 *
 *		Since both pieces of info are needed to know how to copy a Datum,
932
 *		many places need both.	Might as well get them with one cache lookup
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
 *		instead of two.  Also, this routine raises an error instead of
 *		returning a bogus value when given a bad type OID.
 */
void
get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
{
	HeapTuple	tp;
	Form_pg_type typtup;

	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "cache lookup failed for type %u", typid);
	typtup = (Form_pg_type) GETSTRUCT(tp);
	*typlen = typtup->typlen;
	*typbyval = typtup->typbyval;
	ReleaseSysCache(tp);
}

953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
/*
 * get_typlenbyvalalign
 *
 *		A three-fer: given the type OID, return typlen, typbyval, typalign.
 */
void
get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
					 char *typalign)
{
	HeapTuple	tp;
	Form_pg_type typtup;

	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
	if (!HeapTupleIsValid(tp))
		elog(ERROR, "cache lookup failed for type %u", typid);
	typtup = (Form_pg_type) GETSTRUCT(tp);
	*typlen = typtup->typlen;
	*typbyval = typtup->typbyval;
	*typalign = typtup->typalign;
	ReleaseSysCache(tp);
}

977
#ifdef NOT_USED
978 979 980
char
get_typalign(Oid typid)
{
981
	HeapTuple	tp;
982

983 984 985
	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
986 987 988
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
989
		char		result;
990

991 992 993
		result = typtup->typalign;
		ReleaseSysCache(tp);
		return result;
994
	}
995
	else
Bruce Momjian's avatar
Bruce Momjian committed
996
		return 'i';
997
}
998
#endif
999

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
char
get_typstorage(Oid typid)
{
	HeapTuple	tp;

	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1011
		char		result;
1012 1013 1014 1015 1016 1017 1018 1019 1020

		result = typtup->typstorage;
		ReleaseSysCache(tp);
		return result;
	}
	else
		return 'p';
}

1021
/*
1022
 * get_typdefault
1023
 *	  Given a type OID, return the type's default value, if any.
Tom Lane's avatar
Tom Lane committed
1024 1025 1026 1027 1028 1029
 *
 *	  The result is a palloc'd expression node tree, or NULL if there
 *	  is no defined default for the datatype.
 *
 * NB: caller should be prepared to coerce result to correct datatype;
 * the returned expression tree might produce something of the wrong type.
1030
 */
1031
Node *
Tom Lane's avatar
Tom Lane committed
1032
get_typdefault(Oid typid)
1033
{
1034 1035
	HeapTuple	typeTuple;
	Form_pg_type type;
1036
	Datum		datum;
1037
	bool		isNull;
1038
	Node	   *expr;
1039

1040 1041 1042
	typeTuple = SearchSysCache(TYPEOID,
							   ObjectIdGetDatum(typid),
							   0, 0, 0);
1043 1044 1045
	if (!HeapTupleIsValid(typeTuple))
		elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
	type = (Form_pg_type) GETSTRUCT(typeTuple);
1046 1047

	/*
Tom Lane's avatar
Tom Lane committed
1048 1049 1050
	 * typdefault and typdefaultbin are potentially null, so don't try to
	 * access 'em as struct fields. Must do it the hard way with
	 * SysCacheGetAttr.
1051
	 */
1052 1053 1054 1055
	datum = SysCacheGetAttr(TYPEOID,
							typeTuple,
							Anum_pg_type_typdefaultbin,
							&isNull);
1056

Tom Lane's avatar
Tom Lane committed
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
	if (!isNull)
	{
		/* We have an expression default */
		expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
																datum)));
	}
	else
	{
		/* Perhaps we have a plain literal default */
		datum = SysCacheGetAttr(TYPEOID,
								typeTuple,
								Anum_pg_type_typdefault,
								&isNull);

		if (!isNull)
		{
			char	   *strDefaultVal;

			/* Convert text datum to C string */
			strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
																datum));
			/* Convert C string to a value of the given type */
			datum = OidFunctionCall3(type->typinput,
									 CStringGetDatum(strDefaultVal),
									 ObjectIdGetDatum(type->typelem),
									 Int32GetDatum(-1));
			/* Build a Const node containing the value */
			expr = (Node *) makeConst(typid,
									  type->typlen,
									  datum,
									  false,
1088
									  type->typbyval);
Tom Lane's avatar
Tom Lane committed
1089 1090 1091 1092 1093 1094 1095 1096
			pfree(strDefaultVal);
		}
		else
		{
			/* No default */
			expr = NULL;
		}
	}
1097

Tom Lane's avatar
Tom Lane committed
1098
	ReleaseSysCache(typeTuple);
1099

Tom Lane's avatar
Tom Lane committed
1100 1101
	return expr;
}
Bruce Momjian's avatar
Bruce Momjian committed
1102

Tom Lane's avatar
Tom Lane committed
1103 1104 1105 1106 1107 1108 1109 1110
/*
 * getBaseType
 *		If the given type is a domain, return its base type;
 *		otherwise return the type's own OID.
 */
Oid
getBaseType(Oid typid)
{
1111
	/*
Tom Lane's avatar
Tom Lane committed
1112
	 * We loop to find the bottom base type in a stack of domains.
1113
	 */
Tom Lane's avatar
Tom Lane committed
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
	for (;;)
	{
		HeapTuple	tup;
		Form_pg_type typTup;

		tup = SearchSysCache(TYPEOID,
							 ObjectIdGetDatum(typid),
							 0, 0, 0);
		if (!HeapTupleIsValid(tup))
			elog(ERROR, "getBaseType: failed to lookup type %u", typid);
		typTup = (Form_pg_type) GETSTRUCT(tup);
		if (typTup->typtype != 'd')
		{
			/* Not a domain, so done */
			ReleaseSysCache(tup);
			break;
		}
1131

Tom Lane's avatar
Tom Lane committed
1132 1133 1134
		typid = typTup->typbasetype;
		ReleaseSysCache(tup);
	}
1135

Tom Lane's avatar
Tom Lane committed
1136
	return typid;
1137 1138
}

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
/*
 * get_typavgwidth
 *
 *	  Given a type OID and a typmod value (pass -1 if typmod is unknown),
 *	  estimate the average width of values of the type.  This is used by
 *	  the planner, which doesn't require absolutely correct results;
 *	  it's OK (and expected) to guess if we don't know for sure.
 */
int32
get_typavgwidth(Oid typid, int32 typmod)
{
	int			typlen = get_typlen(typid);
	int32		maxwidth;

	/*
	 * Easy if it's a fixed-width type
	 */
	if (typlen > 0)
		return typlen;
1158

1159 1160 1161 1162 1163 1164 1165 1166
	/*
	 * type_maximum_size knows the encoding of typmod for some datatypes;
	 * don't duplicate that knowledge here.
	 */
	maxwidth = type_maximum_size(typid, typmod);
	if (maxwidth > 0)
	{
		/*
1167 1168 1169
		 * For BPCHAR, the max width is also the only width.  Otherwise we
		 * need to guess about the typical data width given the max. A
		 * sliding scale for percentage of max width seems reasonable.
1170 1171 1172 1173 1174 1175
		 */
		if (typid == BPCHAROID)
			return maxwidth;
		if (maxwidth <= 32)
			return maxwidth;	/* assume full width */
		if (maxwidth < 1000)
1176 1177
			return 32 + (maxwidth - 32) / 2;	/* assume 50% */

1178 1179 1180 1181 1182 1183 1184
		/*
		 * Beyond 1000, assume we're looking at something like
		 * "varchar(10000)" where the limit isn't actually reached often,
		 * and use a fixed estimate.
		 */
		return 32 + (1000 - 32) / 2;
	}
1185

1186 1187 1188 1189 1190 1191
	/*
	 * Ooops, we have no idea ... wild guess time.
	 */
	return 32;
}

1192
/*
1193
 * get_typtype
1194
 *
1195
 *		Given the type OID, find if it is a basic type, a complex type, etc.
1196
 *		It returns the null char if the cache lookup fails...
1197 1198 1199 1200
 */
char
get_typtype(Oid typid)
{
1201
	HeapTuple	tp;
1202

1203 1204 1205
	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
1206 1207 1208
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1209
		char		result;
1210

1211 1212 1213
		result = typtup->typtype;
		ReleaseSysCache(tp);
		return result;
1214
	}
1215
	else
Bruce Momjian's avatar
Bruce Momjian committed
1216
		return '\0';
1217
}
1218

1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
/*
 * get_typ_typrelid
 *
 *		Given the type OID, get the typrelid (InvalidOid if not a complex
 *		type).
 */
Oid
get_typ_typrelid(Oid typid)
{
	HeapTuple	tp;

	tp = SearchSysCache(TYPEOID,
						ObjectIdGetDatum(typid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
		Oid			result;

		result = typtup->typrelid;
		ReleaseSysCache(tp);
		return result;
	}
	else
		return InvalidOid;
}

1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
/*
 * getTypeInputInfo
 *
 *		Get info needed for converting values of a type to internal form
 */
void
getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem)
{
	HeapTuple	typeTuple;
	Form_pg_type pt;

	typeTuple = SearchSysCache(TYPEOID,
							   ObjectIdGetDatum(type),
							   0, 0, 0);
	if (!HeapTupleIsValid(typeTuple))
		elog(ERROR, "getTypeInputInfo: Cache lookup of type %u failed", type);
	pt = (Form_pg_type) GETSTRUCT(typeTuple);

	if (!pt->typisdefined)
		elog(ERROR, "Type \"%s\" is only a shell", NameStr(pt->typname));

	*typInput = pt->typinput;
	*typElem = pt->typelem;

	ReleaseSysCache(typeTuple);
}

1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
/*
 * getTypeOutputInfo
 *
 *		Get info needed for printing values of a type
 *
 * Returns true if data valid (a false result probably means it's a shell type)
 */
bool
getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
				  bool *typIsVarlena)
{
	HeapTuple	typeTuple;
	Form_pg_type pt;

	typeTuple = SearchSysCache(TYPEOID,
							   ObjectIdGetDatum(type),
							   0, 0, 0);
	if (!HeapTupleIsValid(typeTuple))
		elog(ERROR, "getTypeOutputInfo: Cache lookup of type %u failed", type);
	pt = (Form_pg_type) GETSTRUCT(typeTuple);

	*typOutput = pt->typoutput;
	*typElem = pt->typelem;
	*typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
	ReleaseSysCache(typeTuple);
	return OidIsValid(*typOutput);
}

1301 1302 1303

/*				---------- STATISTICS CACHE ----------					 */

1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
/*
 * get_attavgwidth
 *
 *	  Given the table and attribute number of a column, get the average
 *	  width of entries in the column.  Return zero if no data available.
 */
int32
get_attavgwidth(Oid relid, AttrNumber attnum)
{
	HeapTuple	tp;

	tp = SearchSysCache(STATRELATT,
						ObjectIdGetDatum(relid),
						Int16GetDatum(attnum),
						0, 0);
	if (HeapTupleIsValid(tp))
	{
1321
		int32		stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1322 1323 1324 1325 1326 1327 1328 1329

		ReleaseSysCache(tp);
		if (stawidth > 0)
			return stawidth;
	}
	return 0;
}

1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
/*
 * get_attstatsslot
 *
 *		Extract the contents of a "slot" of a pg_statistic tuple.
 *		Returns TRUE if requested slot type was found, else FALSE.
 *
 * Unlike other routines in this file, this takes a pointer to an
 * already-looked-up tuple in the pg_statistic cache.  We do this since
 * most callers will want to extract more than one value from the cache
 * entry, and we don't want to repeat the cache lookup unnecessarily.
 *
 * statstuple: pg_statistics tuple to be examined.
 * atttype: type OID of attribute.
 * atttypmod: typmod of attribute.
 * reqkind: STAKIND code for desired statistics slot kind.
 * reqop: STAOP value wanted, or InvalidOid if don't care.
 * values, nvalues: if not NULL, the slot's stavalues are extracted.
 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
 *
 * If assigned, values and numbers are set to point to palloc'd arrays.
 * If the attribute type is pass-by-reference, the values referenced by
 * the values array are themselves palloc'd.  The palloc'd stuff can be
 * freed by calling free_attstatsslot.
 */
bool
get_attstatsslot(HeapTuple statstuple,
				 Oid atttype, int32 atttypmod,
				 int reqkind, Oid reqop,
				 Datum **values, int *nvalues,
				 float4 **numbers, int *nnumbers)
{
	Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
	int			i,
				j;
	Datum		val;
	bool		isnull;
	ArrayType  *statarray;
	int			narrayelem;
	HeapTuple	typeTuple;
	FmgrInfo	inputproc;
	Oid			typelem;

	for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
	{
		if ((&stats->stakind1)[i] == reqkind &&
			(reqop == InvalidOid || (&stats->staop1)[i] == reqop))
			break;
	}
	if (i >= STATISTIC_NUM_SLOTS)
		return false;			/* not there */

	if (values)
	{
		val = SysCacheGetAttr(STATRELATT, statstuple,
							  Anum_pg_statistic_stavalues1 + i,
							  &isnull);
		if (isnull)
			elog(ERROR, "get_attstatsslot: stavalues is null");
		statarray = DatumGetArrayTypeP(val);
1389

1390
		/*
1391 1392
		 * Do initial examination of the array.  This produces a list of
		 * text Datums --- ie, pointers into the text array value.
1393
		 */
1394 1395 1396
		deconstruct_array(statarray,
						  TEXTOID, -1, false, 'i',
						  values, nvalues);
1397
		narrayelem = *nvalues;
1398

1399
		/*
1400 1401
		 * We now need to replace each text Datum by its internal
		 * equivalent.
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
		 *
		 * Get the type input proc and typelem for the column datatype.
		 */
		typeTuple = SearchSysCache(TYPEOID,
								   ObjectIdGetDatum(atttype),
								   0, 0, 0);
		if (!HeapTupleIsValid(typeTuple))
			elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u",
				 atttype);
		fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc);
		typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
		ReleaseSysCache(typeTuple);
1414

1415
		/*
1416 1417
		 * Do the conversions.	The palloc'd array of Datums is reused in
		 * place.
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
		 */
		for (j = 0; j < narrayelem; j++)
		{
			char	   *strval;

			strval = DatumGetCString(DirectFunctionCall1(textout,
														 (*values)[j]));
			(*values)[j] = FunctionCall3(&inputproc,
										 CStringGetDatum(strval),
										 ObjectIdGetDatum(typelem),
										 Int32GetDatum(atttypmod));
			pfree(strval);
		}
1431

1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446
		/*
		 * Free statarray if it's a detoasted copy.
		 */
		if ((Pointer) statarray != DatumGetPointer(val))
			pfree(statarray);
	}

	if (numbers)
	{
		val = SysCacheGetAttr(STATRELATT, statstuple,
							  Anum_pg_statistic_stanumbers1 + i,
							  &isnull);
		if (isnull)
			elog(ERROR, "get_attstatsslot: stanumbers is null");
		statarray = DatumGetArrayTypeP(val);
1447

1448
		/*
1449 1450 1451
		 * We expect the array to be a 1-D float4 array; verify that. We
		 * don't need to use deconstruct_array() since the array data is
		 * just going to look like a C array of float4 values.
1452 1453 1454
		 */
		narrayelem = ARR_DIMS(statarray)[0];
		if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1455 1456
			ARR_ELEMTYPE(statarray) != FLOAT4OID)
			elog(ERROR, "get_attstatsslot: stanumbers is not a 1-D float4 array");
1457 1458 1459
		*numbers = (float4 *) palloc(narrayelem * sizeof(float4));
		memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
		*nnumbers = narrayelem;
1460

1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
		/*
		 * Free statarray if it's a detoasted copy.
		 */
		if ((Pointer) statarray != DatumGetPointer(val))
			pfree(statarray);
	}

	return true;
}

void
free_attstatsslot(Oid atttype,
				  Datum *values, int nvalues,
				  float4 *numbers, int nnumbers)
{
	if (values)
	{
1478
		if (!get_typbyval(atttype))
1479
		{
1480
			int			i;
1481 1482 1483 1484 1485 1486 1487 1488 1489

			for (i = 0; i < nvalues; i++)
				pfree(DatumGetPointer(values[i]));
		}
		pfree(values);
	}
	if (numbers)
		pfree(numbers);
}
1490

1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
/*				---------- PG_NAMESPACE CACHE ----------				 */

/*
 * get_namespace_name
 *		Returns the name of a given namespace
 *
 * Returns a palloc'd copy of the string, or NULL if no such namespace.
 */
char *
get_namespace_name(Oid nspid)
{
	HeapTuple	tp;

	tp = SearchSysCache(NAMESPACEOID,
						ObjectIdGetDatum(nspid),
						0, 0, 0);
	if (HeapTupleIsValid(tp))
	{
		Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
		char	   *result;

		result = pstrdup(NameStr(nsptup->nspname));
		ReleaseSysCache(tp);
		return result;
	}
	else
		return NULL;
}

1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
/*				---------- PG_SHADOW CACHE ----------					 */

/*
 * get_usesysid
 *
 *	  Given a user name, look up the user's sysid.
 *	  Raises an error if no such user (rather than returning zero,
 *	  which might possibly be a valid usesysid).
 *
 * Note: the type of usesysid is currently int4, but may change to Oid
 * someday.  It'd be reasonable to return zero on failure if we were
 * using Oid ...
 */
1533
AclId
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
get_usesysid(const char *username)
{
	int32		result;
	HeapTuple	userTup;

	userTup = SearchSysCache(SHADOWNAME,
							 PointerGetDatum(username),
							 0, 0, 0);
	if (!HeapTupleIsValid(userTup))
		elog(ERROR, "user \"%s\" does not exist", username);

	result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;

	ReleaseSysCache(userTup);

	return result;
}