Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * lsyscache.c
4 : * Convenience routines for common queries in the system catalog cache.
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * IDENTIFICATION
10 : * src/backend/utils/cache/lsyscache.c
11 : *
12 : * NOTES
13 : * Eventually, the index information should go through here, too.
14 : *-------------------------------------------------------------------------
15 : */
16 : #include "postgres.h"
17 :
18 : #include "access/hash.h"
19 : #include "access/htup_details.h"
20 : #include "access/nbtree.h"
21 : #include "bootstrap/bootstrap.h"
22 : #include "catalog/namespace.h"
23 : #include "catalog/pg_am.h"
24 : #include "catalog/pg_amop.h"
25 : #include "catalog/pg_amproc.h"
26 : #include "catalog/pg_cast.h"
27 : #include "catalog/pg_collation.h"
28 : #include "catalog/pg_constraint.h"
29 : #include "catalog/pg_language.h"
30 : #include "catalog/pg_namespace.h"
31 : #include "catalog/pg_opclass.h"
32 : #include "catalog/pg_operator.h"
33 : #include "catalog/pg_proc.h"
34 : #include "catalog/pg_range.h"
35 : #include "catalog/pg_statistic.h"
36 : #include "catalog/pg_subscription.h"
37 : #include "catalog/pg_transform.h"
38 : #include "catalog/pg_type.h"
39 : #include "miscadmin.h"
40 : #include "nodes/makefuncs.h"
41 : #include "utils/array.h"
42 : #include "utils/builtins.h"
43 : #include "utils/catcache.h"
44 : #include "utils/datum.h"
45 : #include "utils/fmgroids.h"
46 : #include "utils/lsyscache.h"
47 : #include "utils/rel.h"
48 : #include "utils/syscache.h"
49 : #include "utils/typcache.h"
50 :
51 : /* Hook for plugins to get control in get_attavgwidth() */
52 : get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
53 :
54 :
55 : /* ---------- AMOP CACHES ---------- */
56 :
57 : /*
58 : * op_in_opfamily
59 : *
60 : * Return t iff operator 'opno' is in operator family 'opfamily'.
61 : *
62 : * This function only considers search operators, not ordering operators.
63 : */
64 : bool
65 440372 : op_in_opfamily(Oid opno, Oid opfamily)
66 : {
67 440372 : return SearchSysCacheExists3(AMOPOPID,
68 : ObjectIdGetDatum(opno),
69 : CharGetDatum(AMOP_SEARCH),
70 : ObjectIdGetDatum(opfamily));
71 : }
72 :
73 : /*
74 : * get_op_opfamily_strategy
75 : *
76 : * Get the operator's strategy number within the specified opfamily,
77 : * or 0 if it's not a member of the opfamily.
78 : *
79 : * This function only considers search operators, not ordering operators.
80 : */
81 : int
82 521426 : get_op_opfamily_strategy(Oid opno, Oid opfamily)
83 : {
84 : HeapTuple tp;
85 : Form_pg_amop amop_tup;
86 : int result;
87 :
88 521426 : tp = SearchSysCache3(AMOPOPID,
89 : ObjectIdGetDatum(opno),
90 : CharGetDatum(AMOP_SEARCH),
91 : ObjectIdGetDatum(opfamily));
92 521426 : if (!HeapTupleIsValid(tp))
93 0 : return 0;
94 521426 : amop_tup = (Form_pg_amop) GETSTRUCT(tp);
95 521426 : result = amop_tup->amopstrategy;
96 521426 : ReleaseSysCache(tp);
97 521426 : return result;
98 : }
99 :
100 : /*
101 : * get_op_opfamily_sortfamily
102 : *
103 : * If the operator is an ordering operator within the specified opfamily,
104 : * return its amopsortfamily OID; else return InvalidOid.
105 : */
106 : Oid
107 474 : get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
108 : {
109 : HeapTuple tp;
110 : Form_pg_amop amop_tup;
111 : Oid result;
112 :
113 474 : tp = SearchSysCache3(AMOPOPID,
114 : ObjectIdGetDatum(opno),
115 : CharGetDatum(AMOP_ORDER),
116 : ObjectIdGetDatum(opfamily));
117 474 : if (!HeapTupleIsValid(tp))
118 0 : return InvalidOid;
119 474 : amop_tup = (Form_pg_amop) GETSTRUCT(tp);
120 474 : result = amop_tup->amopsortfamily;
121 474 : ReleaseSysCache(tp);
122 474 : return result;
123 : }
124 :
125 : /*
126 : * get_op_opfamily_properties
127 : *
128 : * Get the operator's strategy number and declared input data types
129 : * within the specified opfamily.
130 : *
131 : * Caller should already have verified that opno is a member of opfamily,
132 : * therefore we raise an error if the tuple is not found.
133 : */
134 : void
135 302784 : get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
136 : int *strategy,
137 : Oid *lefttype,
138 : Oid *righttype)
139 : {
140 : HeapTuple tp;
141 : Form_pg_amop amop_tup;
142 :
143 302784 : tp = SearchSysCache3(AMOPOPID,
144 : ObjectIdGetDatum(opno),
145 : CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
146 : ObjectIdGetDatum(opfamily));
147 302784 : if (!HeapTupleIsValid(tp))
148 0 : elog(ERROR, "operator %u is not a member of opfamily %u",
149 : opno, opfamily);
150 302784 : amop_tup = (Form_pg_amop) GETSTRUCT(tp);
151 302784 : *strategy = amop_tup->amopstrategy;
152 302784 : *lefttype = amop_tup->amoplefttype;
153 302784 : *righttype = amop_tup->amoprighttype;
154 302784 : ReleaseSysCache(tp);
155 302784 : }
156 :
157 : /*
158 : * get_opfamily_member
159 : * Get the OID of the operator that implements the specified strategy
160 : * with the specified datatypes for the specified opfamily.
161 : *
162 : * Returns InvalidOid if there is no pg_amop entry for the given keys.
163 : */
164 : Oid
165 2625378 : get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
166 : int16 strategy)
167 : {
168 : HeapTuple tp;
169 : Form_pg_amop amop_tup;
170 : Oid result;
171 :
172 2625378 : tp = SearchSysCache4(AMOPSTRATEGY,
173 : ObjectIdGetDatum(opfamily),
174 : ObjectIdGetDatum(lefttype),
175 : ObjectIdGetDatum(righttype),
176 : Int16GetDatum(strategy));
177 2625378 : if (!HeapTupleIsValid(tp))
178 372 : return InvalidOid;
179 2625006 : amop_tup = (Form_pg_amop) GETSTRUCT(tp);
180 2625006 : result = amop_tup->amopopr;
181 2625006 : ReleaseSysCache(tp);
182 2625006 : return result;
183 : }
184 :
185 : /*
186 : * get_ordering_op_properties
187 : * Given the OID of an ordering operator (a btree "<" or ">" operator),
188 : * determine its opfamily, its declared input datatype, and its
189 : * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
190 : *
191 : * Returns true if successful, false if no matching pg_amop entry exists.
192 : * (This indicates that the operator is not a valid ordering operator.)
193 : *
194 : * Note: the operator could be registered in multiple families, for example
195 : * if someone were to build a "reverse sort" opfamily. This would result in
196 : * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
197 : * or NULLS LAST, as well as inefficient planning due to failure to match up
198 : * pathkeys that should be the same. So we want a determinate result here.
199 : * Because of the way the syscache search works, we'll use the interpretation
200 : * associated with the opfamily with smallest OID, which is probably
201 : * determinate enough. Since there is no longer any particularly good reason
202 : * to build reverse-sort opfamilies, it doesn't seem worth expending any
203 : * additional effort on ensuring consistency.
204 : */
205 : bool
206 323182 : get_ordering_op_properties(Oid opno,
207 : Oid *opfamily, Oid *opcintype, int16 *strategy)
208 : {
209 323182 : bool result = false;
210 : CatCList *catlist;
211 : int i;
212 :
213 : /* ensure outputs are initialized on failure */
214 323182 : *opfamily = InvalidOid;
215 323182 : *opcintype = InvalidOid;
216 323182 : *strategy = 0;
217 :
218 : /*
219 : * Search pg_amop to see if the target operator is registered as the "<"
220 : * or ">" operator of any btree opfamily.
221 : */
222 323182 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
223 :
224 323182 : for (i = 0; i < catlist->n_members; i++)
225 : {
226 323182 : HeapTuple tuple = &catlist->members[i]->tuple;
227 323182 : Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
228 :
229 : /* must be btree */
230 323182 : if (aform->amopmethod != BTREE_AM_OID)
231 0 : continue;
232 :
233 323182 : if (aform->amopstrategy == BTLessStrategyNumber ||
234 6474 : aform->amopstrategy == BTGreaterStrategyNumber)
235 : {
236 : /* Found it ... should have consistent input types */
237 323182 : if (aform->amoplefttype == aform->amoprighttype)
238 : {
239 : /* Found a suitable opfamily, return info */
240 323182 : *opfamily = aform->amopfamily;
241 323182 : *opcintype = aform->amoplefttype;
242 323182 : *strategy = aform->amopstrategy;
243 323182 : result = true;
244 323182 : break;
245 : }
246 : }
247 : }
248 :
249 323182 : ReleaseSysCacheList(catlist);
250 :
251 323182 : return result;
252 : }
253 :
254 : /*
255 : * get_equality_op_for_ordering_op
256 : * Get the OID of the datatype-specific btree equality operator
257 : * associated with an ordering operator (a "<" or ">" operator).
258 : *
259 : * If "reverse" isn't NULL, also set *reverse to false if the operator is "<",
260 : * true if it's ">"
261 : *
262 : * Returns InvalidOid if no matching equality operator can be found.
263 : * (This indicates that the operator is not a valid ordering operator.)
264 : */
265 : Oid
266 1336 : get_equality_op_for_ordering_op(Oid opno, bool *reverse)
267 : {
268 1336 : Oid result = InvalidOid;
269 : Oid opfamily;
270 : Oid opcintype;
271 : int16 strategy;
272 :
273 : /* Find the operator in pg_amop */
274 1336 : if (get_ordering_op_properties(opno,
275 : &opfamily, &opcintype, &strategy))
276 : {
277 : /* Found a suitable opfamily, get matching equality operator */
278 1336 : result = get_opfamily_member(opfamily,
279 : opcintype,
280 : opcintype,
281 : BTEqualStrategyNumber);
282 1336 : if (reverse)
283 940 : *reverse = (strategy == BTGreaterStrategyNumber);
284 : }
285 :
286 1336 : return result;
287 : }
288 :
289 : /*
290 : * get_ordering_op_for_equality_op
291 : * Get the OID of a datatype-specific btree ordering operator
292 : * associated with an equality operator. (If there are multiple
293 : * possibilities, assume any one will do.)
294 : *
295 : * This function is used when we have to sort data before unique-ifying,
296 : * and don't much care which sorting op is used as long as it's compatible
297 : * with the intended equality operator. Since we need a sorting operator,
298 : * it should be single-data-type even if the given operator is cross-type.
299 : * The caller specifies whether to find an op for the LHS or RHS data type.
300 : *
301 : * Returns InvalidOid if no matching ordering operator can be found.
302 : */
303 : Oid
304 2 : get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
305 : {
306 2 : Oid result = InvalidOid;
307 : CatCList *catlist;
308 : int i;
309 :
310 : /*
311 : * Search pg_amop to see if the target operator is registered as the "="
312 : * operator of any btree opfamily.
313 : */
314 2 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
315 :
316 2 : for (i = 0; i < catlist->n_members; i++)
317 : {
318 2 : HeapTuple tuple = &catlist->members[i]->tuple;
319 2 : Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
320 :
321 : /* must be btree */
322 2 : if (aform->amopmethod != BTREE_AM_OID)
323 0 : continue;
324 :
325 2 : if (aform->amopstrategy == BTEqualStrategyNumber)
326 : {
327 : /* Found a suitable opfamily, get matching ordering operator */
328 : Oid typid;
329 :
330 2 : typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
331 2 : result = get_opfamily_member(aform->amopfamily,
332 : typid, typid,
333 : BTLessStrategyNumber);
334 2 : if (OidIsValid(result))
335 2 : break;
336 : /* failure probably shouldn't happen, but keep looking if so */
337 : }
338 : }
339 :
340 2 : ReleaseSysCacheList(catlist);
341 :
342 2 : return result;
343 : }
344 :
345 : /*
346 : * get_mergejoin_opfamilies
347 : * Given a putatively mergejoinable operator, return a list of the OIDs
348 : * of the btree opfamilies in which it represents equality.
349 : *
350 : * It is possible (though at present unusual) for an operator to be equality
351 : * in more than one opfamily, hence the result is a list. This also lets us
352 : * return NIL if the operator is not found in any opfamilies.
353 : *
354 : * The planner currently uses simple equal() tests to compare the lists
355 : * returned by this function, which makes the list order relevant, though
356 : * strictly speaking it should not be. Because of the way syscache list
357 : * searches are handled, in normal operation the result will be sorted by OID
358 : * so everything works fine. If running with system index usage disabled,
359 : * the result ordering is unspecified and hence the planner might fail to
360 : * recognize optimization opportunities ... but that's hardly a scenario in
361 : * which performance is good anyway, so there's no point in expending code
362 : * or cycles here to guarantee the ordering in that case.
363 : */
364 : List *
365 1724302 : get_mergejoin_opfamilies(Oid opno)
366 : {
367 1724302 : List *result = NIL;
368 : CatCList *catlist;
369 : int i;
370 :
371 : /*
372 : * Search pg_amop to see if the target operator is registered as the "="
373 : * operator of any btree opfamily.
374 : */
375 1724302 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
376 :
377 10301464 : for (i = 0; i < catlist->n_members; i++)
378 : {
379 8577162 : HeapTuple tuple = &catlist->members[i]->tuple;
380 8577162 : Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
381 :
382 : /* must be btree equality */
383 8577162 : if (aform->amopmethod == BTREE_AM_OID &&
384 1757786 : aform->amopstrategy == BTEqualStrategyNumber)
385 1757786 : result = lappend_oid(result, aform->amopfamily);
386 : }
387 :
388 1724302 : ReleaseSysCacheList(catlist);
389 :
390 1724302 : return result;
391 : }
392 :
393 : /*
394 : * get_compatible_hash_operators
395 : * Get the OID(s) of hash equality operator(s) compatible with the given
396 : * operator, but operating on its LHS and/or RHS datatype.
397 : *
398 : * An operator for the LHS type is sought and returned into *lhs_opno if
399 : * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
400 : * and returned into *rhs_opno if rhs_opno isn't NULL.
401 : *
402 : * If the given operator is not cross-type, the results should be the same
403 : * operator, but in cross-type situations they will be different.
404 : *
405 : * Returns true if able to find the requested operator(s), false if not.
406 : * (This indicates that the operator should not have been marked oprcanhash.)
407 : */
408 : bool
409 1614 : get_compatible_hash_operators(Oid opno,
410 : Oid *lhs_opno, Oid *rhs_opno)
411 : {
412 1614 : bool result = false;
413 : CatCList *catlist;
414 : int i;
415 :
416 : /* Ensure output args are initialized on failure */
417 1614 : if (lhs_opno)
418 0 : *lhs_opno = InvalidOid;
419 1614 : if (rhs_opno)
420 1614 : *rhs_opno = InvalidOid;
421 :
422 : /*
423 : * Search pg_amop to see if the target operator is registered as the "="
424 : * operator of any hash opfamily. If the operator is registered in
425 : * multiple opfamilies, assume we can use any one.
426 : */
427 1614 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
428 :
429 3228 : for (i = 0; i < catlist->n_members; i++)
430 : {
431 3228 : HeapTuple tuple = &catlist->members[i]->tuple;
432 3228 : Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
433 :
434 3228 : if (aform->amopmethod == HASH_AM_OID &&
435 1614 : aform->amopstrategy == HTEqualStrategyNumber)
436 : {
437 : /* No extra lookup needed if given operator is single-type */
438 1614 : if (aform->amoplefttype == aform->amoprighttype)
439 : {
440 1566 : if (lhs_opno)
441 0 : *lhs_opno = opno;
442 1566 : if (rhs_opno)
443 1566 : *rhs_opno = opno;
444 1566 : result = true;
445 1566 : break;
446 : }
447 :
448 : /*
449 : * Get the matching single-type operator(s). Failure probably
450 : * shouldn't happen --- it implies a bogus opfamily --- but
451 : * continue looking if so.
452 : */
453 48 : if (lhs_opno)
454 : {
455 0 : *lhs_opno = get_opfamily_member(aform->amopfamily,
456 : aform->amoplefttype,
457 : aform->amoplefttype,
458 : HTEqualStrategyNumber);
459 0 : if (!OidIsValid(*lhs_opno))
460 0 : continue;
461 : /* Matching LHS found, done if caller doesn't want RHS */
462 0 : if (!rhs_opno)
463 : {
464 0 : result = true;
465 0 : break;
466 : }
467 : }
468 48 : if (rhs_opno)
469 : {
470 48 : *rhs_opno = get_opfamily_member(aform->amopfamily,
471 : aform->amoprighttype,
472 : aform->amoprighttype,
473 : HTEqualStrategyNumber);
474 48 : if (!OidIsValid(*rhs_opno))
475 : {
476 : /* Forget any LHS operator from this opfamily */
477 0 : if (lhs_opno)
478 0 : *lhs_opno = InvalidOid;
479 0 : continue;
480 : }
481 : /* Matching RHS found, so done */
482 48 : result = true;
483 48 : break;
484 : }
485 : }
486 : }
487 :
488 1614 : ReleaseSysCacheList(catlist);
489 :
490 1614 : return result;
491 : }
492 :
493 : /*
494 : * get_op_hash_functions
495 : * Get the OID(s) of the standard hash support function(s) compatible with
496 : * the given operator, operating on its LHS and/or RHS datatype as required.
497 : *
498 : * A function for the LHS type is sought and returned into *lhs_procno if
499 : * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
500 : * and returned into *rhs_procno if rhs_procno isn't NULL.
501 : *
502 : * If the given operator is not cross-type, the results should be the same
503 : * function, but in cross-type situations they will be different.
504 : *
505 : * Returns true if able to find the requested function(s), false if not.
506 : * (This indicates that the operator should not have been marked oprcanhash.)
507 : */
508 : bool
509 51708 : get_op_hash_functions(Oid opno,
510 : RegProcedure *lhs_procno, RegProcedure *rhs_procno)
511 : {
512 51708 : bool result = false;
513 : CatCList *catlist;
514 : int i;
515 :
516 : /* Ensure output args are initialized on failure */
517 51708 : if (lhs_procno)
518 51708 : *lhs_procno = InvalidOid;
519 51708 : if (rhs_procno)
520 51708 : *rhs_procno = InvalidOid;
521 :
522 : /*
523 : * Search pg_amop to see if the target operator is registered as the "="
524 : * operator of any hash opfamily. If the operator is registered in
525 : * multiple opfamilies, assume we can use any one.
526 : */
527 51708 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
528 :
529 103736 : for (i = 0; i < catlist->n_members; i++)
530 : {
531 103350 : HeapTuple tuple = &catlist->members[i]->tuple;
532 103350 : Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
533 :
534 103350 : if (aform->amopmethod == HASH_AM_OID &&
535 51322 : aform->amopstrategy == HTEqualStrategyNumber)
536 : {
537 : /*
538 : * Get the matching support function(s). Failure probably
539 : * shouldn't happen --- it implies a bogus opfamily --- but
540 : * continue looking if so.
541 : */
542 51322 : if (lhs_procno)
543 : {
544 51322 : *lhs_procno = get_opfamily_proc(aform->amopfamily,
545 : aform->amoplefttype,
546 : aform->amoplefttype,
547 : HASHSTANDARD_PROC);
548 51322 : if (!OidIsValid(*lhs_procno))
549 0 : continue;
550 : /* Matching LHS found, done if caller doesn't want RHS */
551 51322 : if (!rhs_procno)
552 : {
553 0 : result = true;
554 0 : break;
555 : }
556 : /* Only one lookup needed if given operator is single-type */
557 51322 : if (aform->amoplefttype == aform->amoprighttype)
558 : {
559 51118 : *rhs_procno = *lhs_procno;
560 51118 : result = true;
561 51118 : break;
562 : }
563 : }
564 204 : if (rhs_procno)
565 : {
566 204 : *rhs_procno = get_opfamily_proc(aform->amopfamily,
567 : aform->amoprighttype,
568 : aform->amoprighttype,
569 : HASHSTANDARD_PROC);
570 204 : if (!OidIsValid(*rhs_procno))
571 : {
572 : /* Forget any LHS function from this opfamily */
573 0 : if (lhs_procno)
574 0 : *lhs_procno = InvalidOid;
575 0 : continue;
576 : }
577 : /* Matching RHS found, so done */
578 204 : result = true;
579 204 : break;
580 : }
581 : }
582 : }
583 :
584 51708 : ReleaseSysCacheList(catlist);
585 :
586 51708 : return result;
587 : }
588 :
589 : /*
590 : * get_op_btree_interpretation
591 : * Given an operator's OID, find out which btree opfamilies it belongs to,
592 : * and what properties it has within each one. The results are returned
593 : * as a palloc'd list of OpBtreeInterpretation structs.
594 : *
595 : * In addition to the normal btree operators, we consider a <> operator to be
596 : * a "member" of an opfamily if its negator is an equality operator of the
597 : * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
598 : */
599 : List *
600 4198 : get_op_btree_interpretation(Oid opno)
601 : {
602 4198 : List *result = NIL;
603 : OpBtreeInterpretation *thisresult;
604 : CatCList *catlist;
605 : int i;
606 :
607 : /*
608 : * Find all the pg_amop entries containing the operator.
609 : */
610 4198 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
611 :
612 15884 : for (i = 0; i < catlist->n_members; i++)
613 : {
614 11686 : HeapTuple op_tuple = &catlist->members[i]->tuple;
615 11686 : Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
616 : StrategyNumber op_strategy;
617 :
618 : /* must be btree */
619 11686 : if (op_form->amopmethod != BTREE_AM_OID)
620 8342 : continue;
621 :
622 : /* Get the operator's btree strategy number */
623 3344 : op_strategy = (StrategyNumber) op_form->amopstrategy;
624 : Assert(op_strategy >= 1 && op_strategy <= 5);
625 :
626 : thisresult = (OpBtreeInterpretation *)
627 3344 : palloc(sizeof(OpBtreeInterpretation));
628 3344 : thisresult->opfamily_id = op_form->amopfamily;
629 3344 : thisresult->strategy = op_strategy;
630 3344 : thisresult->oplefttype = op_form->amoplefttype;
631 3344 : thisresult->oprighttype = op_form->amoprighttype;
632 3344 : result = lappend(result, thisresult);
633 : }
634 :
635 4198 : ReleaseSysCacheList(catlist);
636 :
637 : /*
638 : * If we didn't find any btree opfamily containing the operator, perhaps
639 : * it is a <> operator. See if it has a negator that is in an opfamily.
640 : */
641 4198 : if (result == NIL)
642 : {
643 1066 : Oid op_negator = get_negator(opno);
644 :
645 1066 : if (OidIsValid(op_negator))
646 : {
647 1042 : catlist = SearchSysCacheList1(AMOPOPID,
648 : ObjectIdGetDatum(op_negator));
649 :
650 3902 : for (i = 0; i < catlist->n_members; i++)
651 : {
652 2860 : HeapTuple op_tuple = &catlist->members[i]->tuple;
653 2860 : Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
654 : StrategyNumber op_strategy;
655 :
656 : /* must be btree */
657 2860 : if (op_form->amopmethod != BTREE_AM_OID)
658 2198 : continue;
659 :
660 : /* Get the operator's btree strategy number */
661 662 : op_strategy = (StrategyNumber) op_form->amopstrategy;
662 : Assert(op_strategy >= 1 && op_strategy <= 5);
663 :
664 : /* Only consider negators that are = */
665 662 : if (op_strategy != BTEqualStrategyNumber)
666 0 : continue;
667 :
668 : /* OK, report it with "strategy" ROWCOMPARE_NE */
669 : thisresult = (OpBtreeInterpretation *)
670 662 : palloc(sizeof(OpBtreeInterpretation));
671 662 : thisresult->opfamily_id = op_form->amopfamily;
672 662 : thisresult->strategy = ROWCOMPARE_NE;
673 662 : thisresult->oplefttype = op_form->amoplefttype;
674 662 : thisresult->oprighttype = op_form->amoprighttype;
675 662 : result = lappend(result, thisresult);
676 : }
677 :
678 1042 : ReleaseSysCacheList(catlist);
679 : }
680 : }
681 :
682 4198 : return result;
683 : }
684 :
685 : /*
686 : * equality_ops_are_compatible
687 : * Return true if the two given equality operators have compatible
688 : * semantics.
689 : *
690 : * This is trivially true if they are the same operator. Otherwise,
691 : * we look to see if they can be found in the same btree or hash opfamily.
692 : * Either finding allows us to assume that they have compatible notions
693 : * of equality. (The reason we need to do these pushups is that one might
694 : * be a cross-type operator; for instance int24eq vs int4eq.)
695 : */
696 : bool
697 166 : equality_ops_are_compatible(Oid opno1, Oid opno2)
698 : {
699 : bool result;
700 : CatCList *catlist;
701 : int i;
702 :
703 : /* Easy if they're the same operator */
704 166 : if (opno1 == opno2)
705 160 : return true;
706 :
707 : /*
708 : * We search through all the pg_amop entries for opno1.
709 : */
710 6 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
711 :
712 6 : result = false;
713 6 : for (i = 0; i < catlist->n_members; i++)
714 : {
715 6 : HeapTuple op_tuple = &catlist->members[i]->tuple;
716 6 : Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
717 :
718 : /* must be btree or hash */
719 6 : if (op_form->amopmethod == BTREE_AM_OID ||
720 0 : op_form->amopmethod == HASH_AM_OID)
721 : {
722 6 : if (op_in_opfamily(opno2, op_form->amopfamily))
723 : {
724 6 : result = true;
725 6 : break;
726 : }
727 : }
728 : }
729 :
730 6 : ReleaseSysCacheList(catlist);
731 :
732 6 : return result;
733 : }
734 :
735 : /*
736 : * comparison_ops_are_compatible
737 : * Return true if the two given comparison operators have compatible
738 : * semantics.
739 : *
740 : * This is trivially true if they are the same operator. Otherwise,
741 : * we look to see if they can be found in the same btree opfamily.
742 : * For example, '<' and '>=' ops match if they belong to the same family.
743 : *
744 : * (This is identical to equality_ops_are_compatible(), except that we
745 : * don't bother to examine hash opclasses.)
746 : */
747 : bool
748 188100 : comparison_ops_are_compatible(Oid opno1, Oid opno2)
749 : {
750 : bool result;
751 : CatCList *catlist;
752 : int i;
753 :
754 : /* Easy if they're the same operator */
755 188100 : if (opno1 == opno2)
756 88660 : return true;
757 :
758 : /*
759 : * We search through all the pg_amop entries for opno1.
760 : */
761 99440 : catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
762 :
763 99440 : result = false;
764 99764 : for (i = 0; i < catlist->n_members; i++)
765 : {
766 99656 : HeapTuple op_tuple = &catlist->members[i]->tuple;
767 99656 : Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
768 :
769 99656 : if (op_form->amopmethod == BTREE_AM_OID)
770 : {
771 99440 : if (op_in_opfamily(opno2, op_form->amopfamily))
772 : {
773 99332 : result = true;
774 99332 : break;
775 : }
776 : }
777 : }
778 :
779 99440 : ReleaseSysCacheList(catlist);
780 :
781 99440 : return result;
782 : }
783 :
784 :
785 : /* ---------- AMPROC CACHES ---------- */
786 :
787 : /*
788 : * get_opfamily_proc
789 : * Get the OID of the specified support function
790 : * for the specified opfamily and datatypes.
791 : *
792 : * Returns InvalidOid if there is no pg_amproc entry for the given keys.
793 : */
794 : Oid
795 556600 : get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
796 : {
797 : HeapTuple tp;
798 : Form_pg_amproc amproc_tup;
799 : RegProcedure result;
800 :
801 556600 : tp = SearchSysCache4(AMPROCNUM,
802 : ObjectIdGetDatum(opfamily),
803 : ObjectIdGetDatum(lefttype),
804 : ObjectIdGetDatum(righttype),
805 : Int16GetDatum(procnum));
806 556600 : if (!HeapTupleIsValid(tp))
807 21380 : return InvalidOid;
808 535220 : amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
809 535220 : result = amproc_tup->amproc;
810 535220 : ReleaseSysCache(tp);
811 535220 : return result;
812 : }
813 :
814 :
815 : /* ---------- ATTRIBUTE CACHES ---------- */
816 :
817 : /*
818 : * get_attname
819 : * Given the relation id and the attribute number, return the "attname"
820 : * field from the attribute relation as a palloc'ed string.
821 : *
822 : * If no such attribute exists and missing_ok is true, NULL is returned;
823 : * otherwise a not-intended-for-user-consumption error is thrown.
824 : */
825 : char *
826 62474 : get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
827 : {
828 : HeapTuple tp;
829 :
830 62474 : tp = SearchSysCache2(ATTNUM,
831 : ObjectIdGetDatum(relid), Int16GetDatum(attnum));
832 62474 : if (HeapTupleIsValid(tp))
833 : {
834 62450 : Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
835 : char *result;
836 :
837 62450 : result = pstrdup(NameStr(att_tup->attname));
838 62450 : ReleaseSysCache(tp);
839 62450 : return result;
840 : }
841 :
842 24 : if (!missing_ok)
843 0 : elog(ERROR, "cache lookup failed for attribute %d of relation %u",
844 : attnum, relid);
845 24 : return NULL;
846 : }
847 :
848 : /*
849 : * get_attnum
850 : *
851 : * Given the relation id and the attribute name,
852 : * return the "attnum" field from the attribute relation.
853 : *
854 : * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
855 : */
856 : AttrNumber
857 26770 : get_attnum(Oid relid, const char *attname)
858 : {
859 : HeapTuple tp;
860 :
861 26770 : tp = SearchSysCacheAttName(relid, attname);
862 26770 : if (HeapTupleIsValid(tp))
863 : {
864 26670 : Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
865 : AttrNumber result;
866 :
867 26670 : result = att_tup->attnum;
868 26670 : ReleaseSysCache(tp);
869 26670 : return result;
870 : }
871 : else
872 100 : return InvalidAttrNumber;
873 : }
874 :
875 : /*
876 : * get_attstattarget
877 : *
878 : * Given the relation id and the attribute number,
879 : * return the "attstattarget" field from the attribute relation.
880 : *
881 : * Errors if not found.
882 : */
883 : int
884 648 : get_attstattarget(Oid relid, AttrNumber attnum)
885 : {
886 : HeapTuple tp;
887 : Form_pg_attribute att_tup;
888 : int result;
889 :
890 648 : tp = SearchSysCache2(ATTNUM,
891 : ObjectIdGetDatum(relid),
892 : Int16GetDatum(attnum));
893 648 : if (!HeapTupleIsValid(tp))
894 0 : elog(ERROR, "cache lookup failed for attribute %d of relation %u",
895 : attnum, relid);
896 648 : att_tup = (Form_pg_attribute) GETSTRUCT(tp);
897 648 : result = att_tup->attstattarget;
898 648 : ReleaseSysCache(tp);
899 648 : return result;
900 : }
901 :
902 : /*
903 : * get_attgenerated
904 : *
905 : * Given the relation id and the attribute number,
906 : * return the "attgenerated" field from the attribute relation.
907 : *
908 : * Errors if not found.
909 : *
910 : * Since not generated is represented by '\0', this can also be used as a
911 : * Boolean test.
912 : */
913 : char
914 936 : get_attgenerated(Oid relid, AttrNumber attnum)
915 : {
916 : HeapTuple tp;
917 : Form_pg_attribute att_tup;
918 : char result;
919 :
920 936 : tp = SearchSysCache2(ATTNUM,
921 : ObjectIdGetDatum(relid),
922 : Int16GetDatum(attnum));
923 936 : if (!HeapTupleIsValid(tp))
924 0 : elog(ERROR, "cache lookup failed for attribute %d of relation %u",
925 : attnum, relid);
926 936 : att_tup = (Form_pg_attribute) GETSTRUCT(tp);
927 936 : result = att_tup->attgenerated;
928 936 : ReleaseSysCache(tp);
929 936 : return result;
930 : }
931 :
932 : /*
933 : * get_atttype
934 : *
935 : * Given the relation OID and the attribute number with the relation,
936 : * return the attribute type OID.
937 : */
938 : Oid
939 1890 : get_atttype(Oid relid, AttrNumber attnum)
940 : {
941 : HeapTuple tp;
942 :
943 1890 : tp = SearchSysCache2(ATTNUM,
944 : ObjectIdGetDatum(relid),
945 : Int16GetDatum(attnum));
946 1890 : if (HeapTupleIsValid(tp))
947 : {
948 1890 : Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
949 : Oid result;
950 :
951 1890 : result = att_tup->atttypid;
952 1890 : ReleaseSysCache(tp);
953 1890 : return result;
954 : }
955 : else
956 0 : return InvalidOid;
957 : }
958 :
959 : /*
960 : * get_atttypetypmodcoll
961 : *
962 : * A three-fer: given the relation id and the attribute number,
963 : * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
964 : *
965 : * Unlike the otherwise-similar get_atttype, this routine
966 : * raises an error if it can't obtain the information.
967 : */
968 : void
969 11842 : get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
970 : Oid *typid, int32 *typmod, Oid *collid)
971 : {
972 : HeapTuple tp;
973 : Form_pg_attribute att_tup;
974 :
975 11842 : tp = SearchSysCache2(ATTNUM,
976 : ObjectIdGetDatum(relid),
977 : Int16GetDatum(attnum));
978 11842 : if (!HeapTupleIsValid(tp))
979 0 : elog(ERROR, "cache lookup failed for attribute %d of relation %u",
980 : attnum, relid);
981 11842 : att_tup = (Form_pg_attribute) GETSTRUCT(tp);
982 :
983 11842 : *typid = att_tup->atttypid;
984 11842 : *typmod = att_tup->atttypmod;
985 11842 : *collid = att_tup->attcollation;
986 11842 : ReleaseSysCache(tp);
987 11842 : }
988 :
989 : /*
990 : * get_attoptions
991 : *
992 : * Given the relation id and the attribute number,
993 : * return the attribute options text[] datum, if any.
994 : */
995 : Datum
996 624634 : get_attoptions(Oid relid, int16 attnum)
997 : {
998 : HeapTuple tuple;
999 : Datum attopts;
1000 : Datum result;
1001 : bool isnull;
1002 :
1003 624634 : tuple = SearchSysCache2(ATTNUM,
1004 : ObjectIdGetDatum(relid),
1005 : Int16GetDatum(attnum));
1006 :
1007 624634 : if (!HeapTupleIsValid(tuple))
1008 0 : elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1009 : attnum, relid);
1010 :
1011 624634 : attopts = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
1012 : &isnull);
1013 :
1014 624634 : if (isnull)
1015 624296 : result = (Datum) 0;
1016 : else
1017 338 : result = datumCopy(attopts, false, -1); /* text[] */
1018 :
1019 624634 : ReleaseSysCache(tuple);
1020 :
1021 624634 : return result;
1022 : }
1023 :
1024 : /* ---------- PG_CAST CACHE ---------- */
1025 :
1026 : /*
1027 : * get_cast_oid - given two type OIDs, look up a cast OID
1028 : *
1029 : * If missing_ok is false, throw an error if the cast is not found. If
1030 : * true, just return InvalidOid.
1031 : */
1032 : Oid
1033 72 : get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
1034 : {
1035 : Oid oid;
1036 :
1037 72 : oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
1038 : ObjectIdGetDatum(sourcetypeid),
1039 : ObjectIdGetDatum(targettypeid));
1040 72 : if (!OidIsValid(oid) && !missing_ok)
1041 6 : ereport(ERROR,
1042 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1043 : errmsg("cast from type %s to type %s does not exist",
1044 : format_type_be(sourcetypeid),
1045 : format_type_be(targettypeid))));
1046 66 : return oid;
1047 : }
1048 :
1049 : /* ---------- COLLATION CACHE ---------- */
1050 :
1051 : /*
1052 : * get_collation_name
1053 : * Returns the name of a given pg_collation entry.
1054 : *
1055 : * Returns a palloc'd copy of the string, or NULL if no such collation.
1056 : *
1057 : * NOTE: since collation name is not unique, be wary of code that uses this
1058 : * for anything except preparing error messages.
1059 : */
1060 : char *
1061 206 : get_collation_name(Oid colloid)
1062 : {
1063 : HeapTuple tp;
1064 :
1065 206 : tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
1066 206 : if (HeapTupleIsValid(tp))
1067 : {
1068 206 : Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
1069 : char *result;
1070 :
1071 206 : result = pstrdup(NameStr(colltup->collname));
1072 206 : ReleaseSysCache(tp);
1073 206 : return result;
1074 : }
1075 : else
1076 0 : return NULL;
1077 : }
1078 :
1079 : bool
1080 7126 : get_collation_isdeterministic(Oid colloid)
1081 : {
1082 : HeapTuple tp;
1083 : Form_pg_collation colltup;
1084 : bool result;
1085 :
1086 7126 : tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
1087 7126 : if (!HeapTupleIsValid(tp))
1088 0 : elog(ERROR, "cache lookup failed for collation %u", colloid);
1089 7126 : colltup = (Form_pg_collation) GETSTRUCT(tp);
1090 7126 : result = colltup->collisdeterministic;
1091 7126 : ReleaseSysCache(tp);
1092 7126 : return result;
1093 : }
1094 :
1095 : /* ---------- CONSTRAINT CACHE ---------- */
1096 :
1097 : /*
1098 : * get_constraint_name
1099 : * Returns the name of a given pg_constraint entry.
1100 : *
1101 : * Returns a palloc'd copy of the string, or NULL if no such constraint.
1102 : *
1103 : * NOTE: since constraint name is not unique, be wary of code that uses this
1104 : * for anything except preparing error messages.
1105 : */
1106 : char *
1107 646 : get_constraint_name(Oid conoid)
1108 : {
1109 : HeapTuple tp;
1110 :
1111 646 : tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1112 646 : if (HeapTupleIsValid(tp))
1113 : {
1114 646 : Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
1115 : char *result;
1116 :
1117 646 : result = pstrdup(NameStr(contup->conname));
1118 646 : ReleaseSysCache(tp);
1119 646 : return result;
1120 : }
1121 : else
1122 0 : return NULL;
1123 : }
1124 :
1125 : /*
1126 : * get_constraint_index
1127 : * Given the OID of a unique, primary-key, or exclusion constraint,
1128 : * return the OID of the underlying index.
1129 : *
1130 : * Returns InvalidOid if the constraint could not be found or is of
1131 : * the wrong type.
1132 : *
1133 : * The intent of this function is to return the index "owned" by the
1134 : * specified constraint. Therefore we must check contype, since some
1135 : * pg_constraint entries (e.g. for foreign-key constraints) store the
1136 : * OID of an index that is referenced but not owned by the constraint.
1137 : */
1138 : Oid
1139 656 : get_constraint_index(Oid conoid)
1140 : {
1141 : HeapTuple tp;
1142 :
1143 656 : tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1144 656 : if (HeapTupleIsValid(tp))
1145 : {
1146 656 : Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
1147 : Oid result;
1148 :
1149 656 : if (contup->contype == CONSTRAINT_UNIQUE ||
1150 494 : contup->contype == CONSTRAINT_PRIMARY ||
1151 272 : contup->contype == CONSTRAINT_EXCLUSION)
1152 456 : result = contup->conindid;
1153 : else
1154 200 : result = InvalidOid;
1155 656 : ReleaseSysCache(tp);
1156 656 : return result;
1157 : }
1158 : else
1159 0 : return InvalidOid;
1160 : }
1161 :
1162 : /* ---------- LANGUAGE CACHE ---------- */
1163 :
1164 : char *
1165 254 : get_language_name(Oid langoid, bool missing_ok)
1166 : {
1167 : HeapTuple tp;
1168 :
1169 254 : tp = SearchSysCache1(LANGOID, ObjectIdGetDatum(langoid));
1170 254 : if (HeapTupleIsValid(tp))
1171 : {
1172 248 : Form_pg_language lantup = (Form_pg_language) GETSTRUCT(tp);
1173 : char *result;
1174 :
1175 248 : result = pstrdup(NameStr(lantup->lanname));
1176 248 : ReleaseSysCache(tp);
1177 248 : return result;
1178 : }
1179 :
1180 6 : if (!missing_ok)
1181 0 : elog(ERROR, "cache lookup failed for language %u",
1182 : langoid);
1183 6 : return NULL;
1184 : }
1185 :
1186 : /* ---------- OPCLASS CACHE ---------- */
1187 :
1188 : /*
1189 : * get_opclass_family
1190 : *
1191 : * Returns the OID of the operator family the opclass belongs to.
1192 : */
1193 : Oid
1194 182734 : get_opclass_family(Oid opclass)
1195 : {
1196 : HeapTuple tp;
1197 : Form_pg_opclass cla_tup;
1198 : Oid result;
1199 :
1200 182734 : tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1201 182734 : if (!HeapTupleIsValid(tp))
1202 0 : elog(ERROR, "cache lookup failed for opclass %u", opclass);
1203 182734 : cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1204 :
1205 182734 : result = cla_tup->opcfamily;
1206 182734 : ReleaseSysCache(tp);
1207 182734 : return result;
1208 : }
1209 :
1210 : /*
1211 : * get_opclass_input_type
1212 : *
1213 : * Returns the OID of the datatype the opclass indexes.
1214 : */
1215 : Oid
1216 183780 : get_opclass_input_type(Oid opclass)
1217 : {
1218 : HeapTuple tp;
1219 : Form_pg_opclass cla_tup;
1220 : Oid result;
1221 :
1222 183780 : tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1223 183780 : if (!HeapTupleIsValid(tp))
1224 0 : elog(ERROR, "cache lookup failed for opclass %u", opclass);
1225 183780 : cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1226 :
1227 183780 : result = cla_tup->opcintype;
1228 183780 : ReleaseSysCache(tp);
1229 183780 : return result;
1230 : }
1231 :
1232 : /*
1233 : * get_opclass_opfamily_and_input_type
1234 : *
1235 : * Returns the OID of the operator family the opclass belongs to,
1236 : * the OID of the datatype the opclass indexes
1237 : */
1238 : bool
1239 1138 : get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1240 : {
1241 : HeapTuple tp;
1242 : Form_pg_opclass cla_tup;
1243 :
1244 1138 : tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1245 1138 : if (!HeapTupleIsValid(tp))
1246 0 : return false;
1247 :
1248 1138 : cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1249 :
1250 1138 : *opfamily = cla_tup->opcfamily;
1251 1138 : *opcintype = cla_tup->opcintype;
1252 :
1253 1138 : ReleaseSysCache(tp);
1254 :
1255 1138 : return true;
1256 : }
1257 :
1258 : /*
1259 : * get_opclass_method
1260 : *
1261 : * Returns the OID of the index access method the opclass belongs to.
1262 : */
1263 : Oid
1264 144176 : get_opclass_method(Oid opclass)
1265 : {
1266 : HeapTuple tp;
1267 : Form_pg_opclass cla_tup;
1268 : Oid result;
1269 :
1270 144176 : tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1271 144176 : if (!HeapTupleIsValid(tp))
1272 0 : elog(ERROR, "cache lookup failed for opclass %u", opclass);
1273 144176 : cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1274 :
1275 144176 : result = cla_tup->opcmethod;
1276 144176 : ReleaseSysCache(tp);
1277 144176 : return result;
1278 : }
1279 :
1280 : /* ---------- OPERATOR CACHE ---------- */
1281 :
1282 : /*
1283 : * get_opcode
1284 : *
1285 : * Returns the regproc id of the routine used to implement an
1286 : * operator given the operator oid.
1287 : */
1288 : RegProcedure
1289 1227742 : get_opcode(Oid opno)
1290 : {
1291 : HeapTuple tp;
1292 :
1293 1227742 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1294 1227742 : if (HeapTupleIsValid(tp))
1295 : {
1296 1227742 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1297 : RegProcedure result;
1298 :
1299 1227742 : result = optup->oprcode;
1300 1227742 : ReleaseSysCache(tp);
1301 1227742 : return result;
1302 : }
1303 : else
1304 0 : return (RegProcedure) InvalidOid;
1305 : }
1306 :
1307 : /*
1308 : * get_opname
1309 : * returns the name of the operator with the given opno
1310 : *
1311 : * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1312 : */
1313 : char *
1314 66 : get_opname(Oid opno)
1315 : {
1316 : HeapTuple tp;
1317 :
1318 66 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1319 66 : if (HeapTupleIsValid(tp))
1320 : {
1321 66 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1322 : char *result;
1323 :
1324 66 : result = pstrdup(NameStr(optup->oprname));
1325 66 : ReleaseSysCache(tp);
1326 66 : return result;
1327 : }
1328 : else
1329 0 : return NULL;
1330 : }
1331 :
1332 : /*
1333 : * get_op_rettype
1334 : * Given operator oid, return the operator's result type.
1335 : */
1336 : Oid
1337 92 : get_op_rettype(Oid opno)
1338 : {
1339 : HeapTuple tp;
1340 :
1341 92 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1342 92 : if (HeapTupleIsValid(tp))
1343 : {
1344 92 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1345 : Oid result;
1346 :
1347 92 : result = optup->oprresult;
1348 92 : ReleaseSysCache(tp);
1349 92 : return result;
1350 : }
1351 : else
1352 0 : return InvalidOid;
1353 : }
1354 :
1355 : /*
1356 : * op_input_types
1357 : *
1358 : * Returns the left and right input datatypes for an operator
1359 : * (InvalidOid if not relevant).
1360 : */
1361 : void
1362 330792 : op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1363 : {
1364 : HeapTuple tp;
1365 : Form_pg_operator optup;
1366 :
1367 330792 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1368 330792 : if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1369 0 : elog(ERROR, "cache lookup failed for operator %u", opno);
1370 330792 : optup = (Form_pg_operator) GETSTRUCT(tp);
1371 330792 : *lefttype = optup->oprleft;
1372 330792 : *righttype = optup->oprright;
1373 330792 : ReleaseSysCache(tp);
1374 330792 : }
1375 :
1376 : /*
1377 : * op_mergejoinable
1378 : *
1379 : * Returns true if the operator is potentially mergejoinable. (The planner
1380 : * will fail to find any mergejoin plans unless there are suitable btree
1381 : * opfamily entries for this operator and associated sortops. The pg_operator
1382 : * flag is just a hint to tell the planner whether to bother looking.)
1383 : *
1384 : * In some cases (currently only array_eq and record_eq), mergejoinability
1385 : * depends on the specific input data type the operator is invoked for, so
1386 : * that must be passed as well. We currently assume that only one input's type
1387 : * is needed to check this --- by convention, pass the left input's data type.
1388 : */
1389 : bool
1390 435086 : op_mergejoinable(Oid opno, Oid inputtype)
1391 : {
1392 435086 : bool result = false;
1393 : HeapTuple tp;
1394 : TypeCacheEntry *typentry;
1395 :
1396 : /*
1397 : * For array_eq or record_eq, we can sort if the element or field types
1398 : * are all sortable. We could implement all the checks for that here, but
1399 : * the typcache already does that and caches the results too, so let's
1400 : * rely on the typcache.
1401 : */
1402 435086 : if (opno == ARRAY_EQ_OP)
1403 : {
1404 424 : typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1405 424 : if (typentry->cmp_proc == F_BTARRAYCMP)
1406 424 : result = true;
1407 : }
1408 434662 : else if (opno == RECORD_EQ_OP)
1409 : {
1410 64 : typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1411 64 : if (typentry->cmp_proc == F_BTRECORDCMP)
1412 64 : result = true;
1413 : }
1414 : else
1415 : {
1416 : /* For all other operators, rely on pg_operator.oprcanmerge */
1417 434598 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1418 434598 : if (HeapTupleIsValid(tp))
1419 : {
1420 434598 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1421 :
1422 434598 : result = optup->oprcanmerge;
1423 434598 : ReleaseSysCache(tp);
1424 : }
1425 : }
1426 435086 : return result;
1427 : }
1428 :
1429 : /*
1430 : * op_hashjoinable
1431 : *
1432 : * Returns true if the operator is hashjoinable. (There must be a suitable
1433 : * hash opfamily entry for this operator if it is so marked.)
1434 : *
1435 : * In some cases (currently only array_eq), hashjoinability depends on the
1436 : * specific input data type the operator is invoked for, so that must be
1437 : * passed as well. We currently assume that only one input's type is needed
1438 : * to check this --- by convention, pass the left input's data type.
1439 : */
1440 : bool
1441 313218 : op_hashjoinable(Oid opno, Oid inputtype)
1442 : {
1443 313218 : bool result = false;
1444 : HeapTuple tp;
1445 : TypeCacheEntry *typentry;
1446 :
1447 : /* As in op_mergejoinable, let the typcache handle the hard cases */
1448 313218 : if (opno == ARRAY_EQ_OP)
1449 : {
1450 284 : typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1451 284 : if (typentry->hash_proc == F_HASH_ARRAY)
1452 284 : result = true;
1453 : }
1454 312934 : else if (opno == RECORD_EQ_OP)
1455 : {
1456 78 : typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1457 78 : if (typentry->hash_proc == F_HASH_RECORD)
1458 66 : result = true;
1459 : }
1460 : else
1461 : {
1462 : /* For all other operators, rely on pg_operator.oprcanhash */
1463 312856 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1464 312856 : if (HeapTupleIsValid(tp))
1465 : {
1466 312856 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1467 :
1468 312856 : result = optup->oprcanhash;
1469 312856 : ReleaseSysCache(tp);
1470 : }
1471 : }
1472 313218 : return result;
1473 : }
1474 :
1475 : /*
1476 : * op_strict
1477 : *
1478 : * Get the proisstrict flag for the operator's underlying function.
1479 : */
1480 : bool
1481 47870 : op_strict(Oid opno)
1482 : {
1483 47870 : RegProcedure funcid = get_opcode(opno);
1484 :
1485 47870 : if (funcid == (RegProcedure) InvalidOid)
1486 0 : elog(ERROR, "operator %u does not exist", opno);
1487 :
1488 47870 : return func_strict((Oid) funcid);
1489 : }
1490 :
1491 : /*
1492 : * op_volatile
1493 : *
1494 : * Get the provolatile flag for the operator's underlying function.
1495 : */
1496 : char
1497 20182 : op_volatile(Oid opno)
1498 : {
1499 20182 : RegProcedure funcid = get_opcode(opno);
1500 :
1501 20182 : if (funcid == (RegProcedure) InvalidOid)
1502 0 : elog(ERROR, "operator %u does not exist", opno);
1503 :
1504 20182 : return func_volatile((Oid) funcid);
1505 : }
1506 :
1507 : /*
1508 : * get_commutator
1509 : *
1510 : * Returns the corresponding commutator of an operator.
1511 : */
1512 : Oid
1513 71968 : get_commutator(Oid opno)
1514 : {
1515 : HeapTuple tp;
1516 :
1517 71968 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1518 71968 : if (HeapTupleIsValid(tp))
1519 : {
1520 71968 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1521 : Oid result;
1522 :
1523 71968 : result = optup->oprcom;
1524 71968 : ReleaseSysCache(tp);
1525 71968 : return result;
1526 : }
1527 : else
1528 0 : return InvalidOid;
1529 : }
1530 :
1531 : /*
1532 : * get_negator
1533 : *
1534 : * Returns the corresponding negator of an operator.
1535 : */
1536 : Oid
1537 58598 : get_negator(Oid opno)
1538 : {
1539 : HeapTuple tp;
1540 :
1541 58598 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1542 58598 : if (HeapTupleIsValid(tp))
1543 : {
1544 58598 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1545 : Oid result;
1546 :
1547 58598 : result = optup->oprnegate;
1548 58598 : ReleaseSysCache(tp);
1549 58598 : return result;
1550 : }
1551 : else
1552 0 : return InvalidOid;
1553 : }
1554 :
1555 : /*
1556 : * get_oprrest
1557 : *
1558 : * Returns procedure id for computing selectivity of an operator.
1559 : */
1560 : RegProcedure
1561 886642 : get_oprrest(Oid opno)
1562 : {
1563 : HeapTuple tp;
1564 :
1565 886642 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1566 886642 : if (HeapTupleIsValid(tp))
1567 : {
1568 886642 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1569 : RegProcedure result;
1570 :
1571 886642 : result = optup->oprrest;
1572 886642 : ReleaseSysCache(tp);
1573 886642 : return result;
1574 : }
1575 : else
1576 0 : return (RegProcedure) InvalidOid;
1577 : }
1578 :
1579 : /*
1580 : * get_oprjoin
1581 : *
1582 : * Returns procedure id for computing selectivity of a join.
1583 : */
1584 : RegProcedure
1585 179576 : get_oprjoin(Oid opno)
1586 : {
1587 : HeapTuple tp;
1588 :
1589 179576 : tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1590 179576 : if (HeapTupleIsValid(tp))
1591 : {
1592 179576 : Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1593 : RegProcedure result;
1594 :
1595 179576 : result = optup->oprjoin;
1596 179576 : ReleaseSysCache(tp);
1597 179576 : return result;
1598 : }
1599 : else
1600 0 : return (RegProcedure) InvalidOid;
1601 : }
1602 :
1603 : /* ---------- FUNCTION CACHE ---------- */
1604 :
1605 : /*
1606 : * get_func_name
1607 : * returns the name of the function with the given funcid
1608 : *
1609 : * Note: returns a palloc'd copy of the string, or NULL if no such function.
1610 : */
1611 : char *
1612 562 : get_func_name(Oid funcid)
1613 : {
1614 : HeapTuple tp;
1615 :
1616 562 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1617 562 : if (HeapTupleIsValid(tp))
1618 : {
1619 562 : Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1620 : char *result;
1621 :
1622 562 : result = pstrdup(NameStr(functup->proname));
1623 562 : ReleaseSysCache(tp);
1624 562 : return result;
1625 : }
1626 : else
1627 0 : return NULL;
1628 : }
1629 :
1630 : /*
1631 : * get_func_namespace
1632 : *
1633 : * Returns the pg_namespace OID associated with a given function.
1634 : */
1635 : Oid
1636 128 : get_func_namespace(Oid funcid)
1637 : {
1638 : HeapTuple tp;
1639 :
1640 128 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1641 128 : if (HeapTupleIsValid(tp))
1642 : {
1643 128 : Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1644 : Oid result;
1645 :
1646 128 : result = functup->pronamespace;
1647 128 : ReleaseSysCache(tp);
1648 128 : return result;
1649 : }
1650 : else
1651 0 : return InvalidOid;
1652 : }
1653 :
1654 : /*
1655 : * get_func_rettype
1656 : * Given procedure id, return the function's result type.
1657 : */
1658 : Oid
1659 21368 : get_func_rettype(Oid funcid)
1660 : {
1661 : HeapTuple tp;
1662 : Oid result;
1663 :
1664 21368 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1665 21368 : if (!HeapTupleIsValid(tp))
1666 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1667 :
1668 21368 : result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1669 21368 : ReleaseSysCache(tp);
1670 21368 : return result;
1671 : }
1672 :
1673 : /*
1674 : * get_func_nargs
1675 : * Given procedure id, return the number of arguments.
1676 : */
1677 : int
1678 0 : get_func_nargs(Oid funcid)
1679 : {
1680 : HeapTuple tp;
1681 : int result;
1682 :
1683 0 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1684 0 : if (!HeapTupleIsValid(tp))
1685 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1686 :
1687 0 : result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1688 0 : ReleaseSysCache(tp);
1689 0 : return result;
1690 : }
1691 :
1692 : /*
1693 : * get_func_signature
1694 : * Given procedure id, return the function's argument and result types.
1695 : * (The return value is the result type.)
1696 : *
1697 : * The arguments are returned as a palloc'd array.
1698 : */
1699 : Oid
1700 1010 : get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1701 : {
1702 : HeapTuple tp;
1703 : Form_pg_proc procstruct;
1704 : Oid result;
1705 :
1706 1010 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1707 1010 : if (!HeapTupleIsValid(tp))
1708 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1709 :
1710 1010 : procstruct = (Form_pg_proc) GETSTRUCT(tp);
1711 :
1712 1010 : result = procstruct->prorettype;
1713 1010 : *nargs = (int) procstruct->pronargs;
1714 : Assert(*nargs == procstruct->proargtypes.dim1);
1715 1010 : *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1716 1010 : memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1717 :
1718 1010 : ReleaseSysCache(tp);
1719 1010 : return result;
1720 : }
1721 :
1722 : /*
1723 : * get_func_variadictype
1724 : * Given procedure id, return the function's provariadic field.
1725 : */
1726 : Oid
1727 276 : get_func_variadictype(Oid funcid)
1728 : {
1729 : HeapTuple tp;
1730 : Oid result;
1731 :
1732 276 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1733 276 : if (!HeapTupleIsValid(tp))
1734 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1735 :
1736 276 : result = ((Form_pg_proc) GETSTRUCT(tp))->provariadic;
1737 276 : ReleaseSysCache(tp);
1738 276 : return result;
1739 : }
1740 :
1741 : /*
1742 : * get_func_retset
1743 : * Given procedure id, return the function's proretset flag.
1744 : */
1745 : bool
1746 543484 : get_func_retset(Oid funcid)
1747 : {
1748 : HeapTuple tp;
1749 : bool result;
1750 :
1751 543484 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1752 543484 : if (!HeapTupleIsValid(tp))
1753 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1754 :
1755 543484 : result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1756 543484 : ReleaseSysCache(tp);
1757 543484 : return result;
1758 : }
1759 :
1760 : /*
1761 : * func_strict
1762 : * Given procedure id, return the function's proisstrict flag.
1763 : */
1764 : bool
1765 220218 : func_strict(Oid funcid)
1766 : {
1767 : HeapTuple tp;
1768 : bool result;
1769 :
1770 220218 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1771 220218 : if (!HeapTupleIsValid(tp))
1772 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1773 :
1774 220218 : result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1775 220218 : ReleaseSysCache(tp);
1776 220218 : return result;
1777 : }
1778 :
1779 : /*
1780 : * func_volatile
1781 : * Given procedure id, return the function's provolatile flag.
1782 : */
1783 : char
1784 759472 : func_volatile(Oid funcid)
1785 : {
1786 : HeapTuple tp;
1787 : char result;
1788 :
1789 759472 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1790 759472 : if (!HeapTupleIsValid(tp))
1791 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1792 :
1793 759472 : result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1794 759472 : ReleaseSysCache(tp);
1795 759472 : return result;
1796 : }
1797 :
1798 : /*
1799 : * func_parallel
1800 : * Given procedure id, return the function's proparallel flag.
1801 : */
1802 : char
1803 1187046 : func_parallel(Oid funcid)
1804 : {
1805 : HeapTuple tp;
1806 : char result;
1807 :
1808 1187046 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1809 1187046 : if (!HeapTupleIsValid(tp))
1810 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1811 :
1812 1187046 : result = ((Form_pg_proc) GETSTRUCT(tp))->proparallel;
1813 1187046 : ReleaseSysCache(tp);
1814 1187046 : return result;
1815 : }
1816 :
1817 : /*
1818 : * get_func_prokind
1819 : * Given procedure id, return the routine kind.
1820 : */
1821 : char
1822 34876 : get_func_prokind(Oid funcid)
1823 : {
1824 : HeapTuple tp;
1825 : char result;
1826 :
1827 34876 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1828 34876 : if (!HeapTupleIsValid(tp))
1829 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1830 :
1831 34876 : result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
1832 34876 : ReleaseSysCache(tp);
1833 34876 : return result;
1834 : }
1835 :
1836 : /*
1837 : * get_func_leakproof
1838 : * Given procedure id, return the function's leakproof field.
1839 : */
1840 : bool
1841 5124 : get_func_leakproof(Oid funcid)
1842 : {
1843 : HeapTuple tp;
1844 : bool result;
1845 :
1846 5124 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1847 5124 : if (!HeapTupleIsValid(tp))
1848 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
1849 :
1850 5124 : result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
1851 5124 : ReleaseSysCache(tp);
1852 5124 : return result;
1853 : }
1854 :
1855 : /*
1856 : * get_func_support
1857 : *
1858 : * Returns the support function OID associated with a given function,
1859 : * or InvalidOid if there is none.
1860 : */
1861 : RegProcedure
1862 29852 : get_func_support(Oid funcid)
1863 : {
1864 : HeapTuple tp;
1865 :
1866 29852 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1867 29852 : if (HeapTupleIsValid(tp))
1868 : {
1869 29852 : Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1870 : RegProcedure result;
1871 :
1872 29852 : result = functup->prosupport;
1873 29852 : ReleaseSysCache(tp);
1874 29852 : return result;
1875 : }
1876 : else
1877 0 : return (RegProcedure) InvalidOid;
1878 : }
1879 :
1880 : /* ---------- RELATION CACHE ---------- */
1881 :
1882 : /*
1883 : * get_relname_relid
1884 : * Given name and namespace of a relation, look up the OID.
1885 : *
1886 : * Returns InvalidOid if there is no such relation.
1887 : */
1888 : Oid
1889 1262398 : get_relname_relid(const char *relname, Oid relnamespace)
1890 : {
1891 1262398 : return GetSysCacheOid2(RELNAMENSP, Anum_pg_class_oid,
1892 : PointerGetDatum(relname),
1893 : ObjectIdGetDatum(relnamespace));
1894 : }
1895 :
1896 : #ifdef NOT_USED
1897 : /*
1898 : * get_relnatts
1899 : *
1900 : * Returns the number of attributes for a given relation.
1901 : */
1902 : int
1903 : get_relnatts(Oid relid)
1904 : {
1905 : HeapTuple tp;
1906 :
1907 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1908 : if (HeapTupleIsValid(tp))
1909 : {
1910 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1911 : int result;
1912 :
1913 : result = reltup->relnatts;
1914 : ReleaseSysCache(tp);
1915 : return result;
1916 : }
1917 : else
1918 : return InvalidAttrNumber;
1919 : }
1920 : #endif
1921 :
1922 : /*
1923 : * get_rel_name
1924 : * Returns the name of a given relation.
1925 : *
1926 : * Returns a palloc'd copy of the string, or NULL if no such relation.
1927 : *
1928 : * NOTE: since relation name is not unique, be wary of code that uses this
1929 : * for anything except preparing error messages.
1930 : */
1931 : char *
1932 88596 : get_rel_name(Oid relid)
1933 : {
1934 : HeapTuple tp;
1935 :
1936 88596 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1937 88596 : if (HeapTupleIsValid(tp))
1938 : {
1939 88584 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1940 : char *result;
1941 :
1942 88584 : result = pstrdup(NameStr(reltup->relname));
1943 88584 : ReleaseSysCache(tp);
1944 88584 : return result;
1945 : }
1946 : else
1947 12 : return NULL;
1948 : }
1949 :
1950 : /*
1951 : * get_rel_namespace
1952 : *
1953 : * Returns the pg_namespace OID associated with a given relation.
1954 : */
1955 : Oid
1956 317756 : get_rel_namespace(Oid relid)
1957 : {
1958 : HeapTuple tp;
1959 :
1960 317756 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1961 317756 : if (HeapTupleIsValid(tp))
1962 : {
1963 317756 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1964 : Oid result;
1965 :
1966 317756 : result = reltup->relnamespace;
1967 317756 : ReleaseSysCache(tp);
1968 317756 : return result;
1969 : }
1970 : else
1971 0 : return InvalidOid;
1972 : }
1973 :
1974 : /*
1975 : * get_rel_type_id
1976 : *
1977 : * Returns the pg_type OID associated with a given relation.
1978 : *
1979 : * Note: not all pg_class entries have associated pg_type OIDs; so be
1980 : * careful to check for InvalidOid result.
1981 : */
1982 : Oid
1983 6084 : get_rel_type_id(Oid relid)
1984 : {
1985 : HeapTuple tp;
1986 :
1987 6084 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1988 6084 : if (HeapTupleIsValid(tp))
1989 : {
1990 6084 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1991 : Oid result;
1992 :
1993 6084 : result = reltup->reltype;
1994 6084 : ReleaseSysCache(tp);
1995 6084 : return result;
1996 : }
1997 : else
1998 0 : return InvalidOid;
1999 : }
2000 :
2001 : /*
2002 : * get_rel_relkind
2003 : *
2004 : * Returns the relkind associated with a given relation.
2005 : */
2006 : char
2007 155118 : get_rel_relkind(Oid relid)
2008 : {
2009 : HeapTuple tp;
2010 :
2011 155118 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2012 155118 : if (HeapTupleIsValid(tp))
2013 : {
2014 155118 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
2015 : char result;
2016 :
2017 155118 : result = reltup->relkind;
2018 155118 : ReleaseSysCache(tp);
2019 155118 : return result;
2020 : }
2021 : else
2022 0 : return '\0';
2023 : }
2024 :
2025 : /*
2026 : * get_rel_relispartition
2027 : *
2028 : * Returns the relispartition flag associated with a given relation.
2029 : */
2030 : bool
2031 4280 : get_rel_relispartition(Oid relid)
2032 : {
2033 : HeapTuple tp;
2034 :
2035 4280 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2036 4280 : if (HeapTupleIsValid(tp))
2037 : {
2038 4280 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
2039 : bool result;
2040 :
2041 4280 : result = reltup->relispartition;
2042 4280 : ReleaseSysCache(tp);
2043 4280 : return result;
2044 : }
2045 : else
2046 0 : return false;
2047 : }
2048 :
2049 : /*
2050 : * get_rel_tablespace
2051 : *
2052 : * Returns the pg_tablespace OID associated with a given relation.
2053 : *
2054 : * Note: InvalidOid might mean either that we couldn't find the relation,
2055 : * or that it is in the database's default tablespace.
2056 : */
2057 : Oid
2058 7714 : get_rel_tablespace(Oid relid)
2059 : {
2060 : HeapTuple tp;
2061 :
2062 7714 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2063 7714 : if (HeapTupleIsValid(tp))
2064 : {
2065 7714 : Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
2066 : Oid result;
2067 :
2068 7714 : result = reltup->reltablespace;
2069 7714 : ReleaseSysCache(tp);
2070 7714 : return result;
2071 : }
2072 : else
2073 0 : return InvalidOid;
2074 : }
2075 :
2076 : /*
2077 : * get_rel_persistence
2078 : *
2079 : * Returns the relpersistence associated with a given relation.
2080 : */
2081 : char
2082 295284 : get_rel_persistence(Oid relid)
2083 : {
2084 : HeapTuple tp;
2085 : Form_pg_class reltup;
2086 : char result;
2087 :
2088 295284 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2089 295284 : if (!HeapTupleIsValid(tp))
2090 0 : elog(ERROR, "cache lookup failed for relation %u", relid);
2091 295284 : reltup = (Form_pg_class) GETSTRUCT(tp);
2092 295284 : result = reltup->relpersistence;
2093 295284 : ReleaseSysCache(tp);
2094 :
2095 295284 : return result;
2096 : }
2097 :
2098 :
2099 : /* ---------- TRANSFORM CACHE ---------- */
2100 :
2101 : Oid
2102 1546 : get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2103 : {
2104 : HeapTuple tup;
2105 :
2106 1546 : if (!list_member_oid(trftypes, typid))
2107 1384 : return InvalidOid;
2108 :
2109 162 : tup = SearchSysCache2(TRFTYPELANG, ObjectIdGetDatum(typid),
2110 : ObjectIdGetDatum(langid));
2111 162 : if (HeapTupleIsValid(tup))
2112 : {
2113 : Oid funcid;
2114 :
2115 162 : funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2116 162 : ReleaseSysCache(tup);
2117 162 : return funcid;
2118 : }
2119 : else
2120 0 : return InvalidOid;
2121 : }
2122 :
2123 : Oid
2124 2054 : get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2125 : {
2126 : HeapTuple tup;
2127 :
2128 2054 : if (!list_member_oid(trftypes, typid))
2129 1872 : return InvalidOid;
2130 :
2131 182 : tup = SearchSysCache2(TRFTYPELANG, ObjectIdGetDatum(typid),
2132 : ObjectIdGetDatum(langid));
2133 182 : if (HeapTupleIsValid(tup))
2134 : {
2135 : Oid funcid;
2136 :
2137 182 : funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2138 182 : ReleaseSysCache(tup);
2139 182 : return funcid;
2140 : }
2141 : else
2142 0 : return InvalidOid;
2143 : }
2144 :
2145 :
2146 : /* ---------- TYPE CACHE ---------- */
2147 :
2148 : /*
2149 : * get_typisdefined
2150 : *
2151 : * Given the type OID, determine whether the type is defined
2152 : * (if not, it's only a shell).
2153 : */
2154 : bool
2155 278 : get_typisdefined(Oid typid)
2156 : {
2157 : HeapTuple tp;
2158 :
2159 278 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2160 278 : if (HeapTupleIsValid(tp))
2161 : {
2162 278 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2163 : bool result;
2164 :
2165 278 : result = typtup->typisdefined;
2166 278 : ReleaseSysCache(tp);
2167 278 : return result;
2168 : }
2169 : else
2170 0 : return false;
2171 : }
2172 :
2173 : /*
2174 : * get_typlen
2175 : *
2176 : * Given the type OID, return the length of the type.
2177 : */
2178 : int16
2179 2369934 : get_typlen(Oid typid)
2180 : {
2181 : HeapTuple tp;
2182 :
2183 2369934 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2184 2369934 : if (HeapTupleIsValid(tp))
2185 : {
2186 2369934 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2187 : int16 result;
2188 :
2189 2369934 : result = typtup->typlen;
2190 2369934 : ReleaseSysCache(tp);
2191 2369934 : return result;
2192 : }
2193 : else
2194 0 : return 0;
2195 : }
2196 :
2197 : /*
2198 : * get_typbyval
2199 : *
2200 : * Given the type OID, determine whether the type is returned by value or
2201 : * not. Returns true if by value, false if by reference.
2202 : */
2203 : bool
2204 63554 : get_typbyval(Oid typid)
2205 : {
2206 : HeapTuple tp;
2207 :
2208 63554 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2209 63554 : if (HeapTupleIsValid(tp))
2210 : {
2211 63554 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2212 : bool result;
2213 :
2214 63554 : result = typtup->typbyval;
2215 63554 : ReleaseSysCache(tp);
2216 63554 : return result;
2217 : }
2218 : else
2219 0 : return false;
2220 : }
2221 :
2222 : /*
2223 : * get_typlenbyval
2224 : *
2225 : * A two-fer: given the type OID, return both typlen and typbyval.
2226 : *
2227 : * Since both pieces of info are needed to know how to copy a Datum,
2228 : * many places need both. Might as well get them with one cache lookup
2229 : * instead of two. Also, this routine raises an error instead of
2230 : * returning a bogus value when given a bad type OID.
2231 : */
2232 : void
2233 729522 : get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2234 : {
2235 : HeapTuple tp;
2236 : Form_pg_type typtup;
2237 :
2238 729522 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2239 729522 : if (!HeapTupleIsValid(tp))
2240 0 : elog(ERROR, "cache lookup failed for type %u", typid);
2241 729522 : typtup = (Form_pg_type) GETSTRUCT(tp);
2242 729522 : *typlen = typtup->typlen;
2243 729522 : *typbyval = typtup->typbyval;
2244 729522 : ReleaseSysCache(tp);
2245 729522 : }
2246 :
2247 : /*
2248 : * get_typlenbyvalalign
2249 : *
2250 : * A three-fer: given the type OID, return typlen, typbyval, typalign.
2251 : */
2252 : void
2253 1573424 : get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2254 : char *typalign)
2255 : {
2256 : HeapTuple tp;
2257 : Form_pg_type typtup;
2258 :
2259 1573424 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2260 1573424 : if (!HeapTupleIsValid(tp))
2261 0 : elog(ERROR, "cache lookup failed for type %u", typid);
2262 1573424 : typtup = (Form_pg_type) GETSTRUCT(tp);
2263 1573424 : *typlen = typtup->typlen;
2264 1573424 : *typbyval = typtup->typbyval;
2265 1573424 : *typalign = typtup->typalign;
2266 1573424 : ReleaseSysCache(tp);
2267 1573424 : }
2268 :
2269 : /*
2270 : * getTypeIOParam
2271 : * Given a pg_type row, select the type OID to pass to I/O functions
2272 : *
2273 : * Formerly, all I/O functions were passed pg_type.typelem as their second
2274 : * parameter, but we now have a more complex rule about what to pass.
2275 : * This knowledge is intended to be centralized here --- direct references
2276 : * to typelem elsewhere in the code are wrong, if they are associated with
2277 : * I/O calls and not with actual subscripting operations! (But see
2278 : * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2279 : *
2280 : * As of PostgreSQL 8.1, output functions receive only the value itself
2281 : * and not any auxiliary parameters, so the name of this routine is now
2282 : * a bit of a misnomer ... it should be getTypeInputParam.
2283 : */
2284 : Oid
2285 1537350 : getTypeIOParam(HeapTuple typeTuple)
2286 : {
2287 1537350 : Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2288 :
2289 : /*
2290 : * Array types get their typelem as parameter; everybody else gets their
2291 : * own type OID as parameter.
2292 : */
2293 1537350 : if (OidIsValid(typeStruct->typelem))
2294 68228 : return typeStruct->typelem;
2295 : else
2296 1469122 : return typeStruct->oid;
2297 : }
2298 :
2299 : /*
2300 : * get_type_io_data
2301 : *
2302 : * A six-fer: given the type OID, return typlen, typbyval, typalign,
2303 : * typdelim, typioparam, and IO function OID. The IO function
2304 : * returned is controlled by IOFuncSelector
2305 : */
2306 : void
2307 78416 : get_type_io_data(Oid typid,
2308 : IOFuncSelector which_func,
2309 : int16 *typlen,
2310 : bool *typbyval,
2311 : char *typalign,
2312 : char *typdelim,
2313 : Oid *typioparam,
2314 : Oid *func)
2315 : {
2316 : HeapTuple typeTuple;
2317 : Form_pg_type typeStruct;
2318 :
2319 : /*
2320 : * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2321 : * use array_in and array_out during bootstrap.
2322 : */
2323 78416 : if (IsBootstrapProcessingMode())
2324 : {
2325 : Oid typinput;
2326 : Oid typoutput;
2327 :
2328 25600 : boot_get_type_io_data(typid,
2329 : typlen,
2330 : typbyval,
2331 : typalign,
2332 : typdelim,
2333 : typioparam,
2334 : &typinput,
2335 : &typoutput);
2336 25600 : switch (which_func)
2337 : {
2338 25600 : case IOFunc_input:
2339 25600 : *func = typinput;
2340 25600 : break;
2341 0 : case IOFunc_output:
2342 0 : *func = typoutput;
2343 0 : break;
2344 0 : default:
2345 0 : elog(ERROR, "binary I/O not supported during bootstrap");
2346 : break;
2347 : }
2348 25600 : return;
2349 : }
2350 :
2351 52816 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2352 52816 : if (!HeapTupleIsValid(typeTuple))
2353 0 : elog(ERROR, "cache lookup failed for type %u", typid);
2354 52816 : typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2355 :
2356 52816 : *typlen = typeStruct->typlen;
2357 52816 : *typbyval = typeStruct->typbyval;
2358 52816 : *typalign = typeStruct->typalign;
2359 52816 : *typdelim = typeStruct->typdelim;
2360 52816 : *typioparam = getTypeIOParam(typeTuple);
2361 52816 : switch (which_func)
2362 : {
2363 25980 : case IOFunc_input:
2364 25980 : *func = typeStruct->typinput;
2365 25980 : break;
2366 26740 : case IOFunc_output:
2367 26740 : *func = typeStruct->typoutput;
2368 26740 : break;
2369 56 : case IOFunc_receive:
2370 56 : *func = typeStruct->typreceive;
2371 56 : break;
2372 40 : case IOFunc_send:
2373 40 : *func = typeStruct->typsend;
2374 40 : break;
2375 : }
2376 52816 : ReleaseSysCache(typeTuple);
2377 : }
2378 :
2379 : #ifdef NOT_USED
2380 : char
2381 : get_typalign(Oid typid)
2382 : {
2383 : HeapTuple tp;
2384 :
2385 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2386 : if (HeapTupleIsValid(tp))
2387 : {
2388 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2389 : char result;
2390 :
2391 : result = typtup->typalign;
2392 : ReleaseSysCache(tp);
2393 : return result;
2394 : }
2395 : else
2396 : return TYPALIGN_INT;
2397 : }
2398 : #endif
2399 :
2400 : char
2401 71734 : get_typstorage(Oid typid)
2402 : {
2403 : HeapTuple tp;
2404 :
2405 71734 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2406 71734 : if (HeapTupleIsValid(tp))
2407 : {
2408 71734 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2409 : char result;
2410 :
2411 71734 : result = typtup->typstorage;
2412 71734 : ReleaseSysCache(tp);
2413 71734 : return result;
2414 : }
2415 : else
2416 0 : return TYPSTORAGE_PLAIN;
2417 : }
2418 :
2419 : /*
2420 : * get_typdefault
2421 : * Given a type OID, return the type's default value, if any.
2422 : *
2423 : * The result is a palloc'd expression node tree, or NULL if there
2424 : * is no defined default for the datatype.
2425 : *
2426 : * NB: caller should be prepared to coerce result to correct datatype;
2427 : * the returned expression tree might produce something of the wrong type.
2428 : */
2429 : Node *
2430 36476 : get_typdefault(Oid typid)
2431 : {
2432 : HeapTuple typeTuple;
2433 : Form_pg_type type;
2434 : Datum datum;
2435 : bool isNull;
2436 : Node *expr;
2437 :
2438 36476 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2439 36476 : if (!HeapTupleIsValid(typeTuple))
2440 0 : elog(ERROR, "cache lookup failed for type %u", typid);
2441 36476 : type = (Form_pg_type) GETSTRUCT(typeTuple);
2442 :
2443 : /*
2444 : * typdefault and typdefaultbin are potentially null, so don't try to
2445 : * access 'em as struct fields. Must do it the hard way with
2446 : * SysCacheGetAttr.
2447 : */
2448 36476 : datum = SysCacheGetAttr(TYPEOID,
2449 : typeTuple,
2450 : Anum_pg_type_typdefaultbin,
2451 : &isNull);
2452 :
2453 36476 : if (!isNull)
2454 : {
2455 : /* We have an expression default */
2456 206 : expr = stringToNode(TextDatumGetCString(datum));
2457 : }
2458 : else
2459 : {
2460 : /* Perhaps we have a plain literal default */
2461 36270 : datum = SysCacheGetAttr(TYPEOID,
2462 : typeTuple,
2463 : Anum_pg_type_typdefault,
2464 : &isNull);
2465 :
2466 36270 : if (!isNull)
2467 : {
2468 : char *strDefaultVal;
2469 :
2470 : /* Convert text datum to C string */
2471 12 : strDefaultVal = TextDatumGetCString(datum);
2472 : /* Convert C string to a value of the given type */
2473 12 : datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2474 : getTypeIOParam(typeTuple), -1);
2475 : /* Build a Const node containing the value */
2476 12 : expr = (Node *) makeConst(typid,
2477 : -1,
2478 : type->typcollation,
2479 12 : type->typlen,
2480 : datum,
2481 : false,
2482 12 : type->typbyval);
2483 12 : pfree(strDefaultVal);
2484 : }
2485 : else
2486 : {
2487 : /* No default */
2488 36258 : expr = NULL;
2489 : }
2490 : }
2491 :
2492 36476 : ReleaseSysCache(typeTuple);
2493 :
2494 36476 : return expr;
2495 : }
2496 :
2497 : /*
2498 : * getBaseType
2499 : * If the given type is a domain, return its base type;
2500 : * otherwise return the type's own OID.
2501 : */
2502 : Oid
2503 4219416 : getBaseType(Oid typid)
2504 : {
2505 4219416 : int32 typmod = -1;
2506 :
2507 4219416 : return getBaseTypeAndTypmod(typid, &typmod);
2508 : }
2509 :
2510 : /*
2511 : * getBaseTypeAndTypmod
2512 : * If the given type is a domain, return its base type and typmod;
2513 : * otherwise return the type's own OID, and leave *typmod unchanged.
2514 : *
2515 : * Note that the "applied typmod" should be -1 for every domain level
2516 : * above the bottommost; therefore, if the passed-in typid is indeed
2517 : * a domain, *typmod should be -1.
2518 : */
2519 : Oid
2520 5995968 : getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2521 : {
2522 : /*
2523 : * We loop to find the bottom base type in a stack of domains.
2524 : */
2525 : for (;;)
2526 196592 : {
2527 : HeapTuple tup;
2528 : Form_pg_type typTup;
2529 :
2530 5995968 : tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2531 5995968 : if (!HeapTupleIsValid(tup))
2532 0 : elog(ERROR, "cache lookup failed for type %u", typid);
2533 5995968 : typTup = (Form_pg_type) GETSTRUCT(tup);
2534 5995968 : if (typTup->typtype != TYPTYPE_DOMAIN)
2535 : {
2536 : /* Not a domain, so done */
2537 5799376 : ReleaseSysCache(tup);
2538 5799376 : break;
2539 : }
2540 :
2541 : Assert(*typmod == -1);
2542 196592 : typid = typTup->typbasetype;
2543 196592 : *typmod = typTup->typtypmod;
2544 :
2545 196592 : ReleaseSysCache(tup);
2546 : }
2547 :
2548 5799376 : return typid;
2549 : }
2550 :
2551 : /*
2552 : * get_typavgwidth
2553 : *
2554 : * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2555 : * estimate the average width of values of the type. This is used by
2556 : * the planner, which doesn't require absolutely correct results;
2557 : * it's OK (and expected) to guess if we don't know for sure.
2558 : */
2559 : int32
2560 1278306 : get_typavgwidth(Oid typid, int32 typmod)
2561 : {
2562 1278306 : int typlen = get_typlen(typid);
2563 : int32 maxwidth;
2564 :
2565 : /*
2566 : * Easy if it's a fixed-width type
2567 : */
2568 1278306 : if (typlen > 0)
2569 847970 : return typlen;
2570 :
2571 : /*
2572 : * type_maximum_size knows the encoding of typmod for some datatypes;
2573 : * don't duplicate that knowledge here.
2574 : */
2575 430336 : maxwidth = type_maximum_size(typid, typmod);
2576 430336 : if (maxwidth > 0)
2577 : {
2578 : /*
2579 : * For BPCHAR, the max width is also the only width. Otherwise we
2580 : * need to guess about the typical data width given the max. A sliding
2581 : * scale for percentage of max width seems reasonable.
2582 : */
2583 24542 : if (typid == BPCHAROID)
2584 15418 : return maxwidth;
2585 9124 : if (maxwidth <= 32)
2586 5070 : return maxwidth; /* assume full width */
2587 4054 : if (maxwidth < 1000)
2588 4022 : return 32 + (maxwidth - 32) / 2; /* assume 50% */
2589 :
2590 : /*
2591 : * Beyond 1000, assume we're looking at something like
2592 : * "varchar(10000)" where the limit isn't actually reached often, and
2593 : * use a fixed estimate.
2594 : */
2595 32 : return 32 + (1000 - 32) / 2;
2596 : }
2597 :
2598 : /*
2599 : * Oops, we have no idea ... wild guess time.
2600 : */
2601 405794 : return 32;
2602 : }
2603 :
2604 : /*
2605 : * get_typtype
2606 : *
2607 : * Given the type OID, find if it is a basic type, a complex type, etc.
2608 : * It returns the null char if the cache lookup fails...
2609 : */
2610 : char
2611 726938 : get_typtype(Oid typid)
2612 : {
2613 : HeapTuple tp;
2614 :
2615 726938 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2616 726938 : if (HeapTupleIsValid(tp))
2617 : {
2618 726844 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2619 : char result;
2620 :
2621 726844 : result = typtup->typtype;
2622 726844 : ReleaseSysCache(tp);
2623 726844 : return result;
2624 : }
2625 : else
2626 94 : return '\0';
2627 : }
2628 :
2629 : /*
2630 : * type_is_rowtype
2631 : *
2632 : * Convenience function to determine whether a type OID represents
2633 : * a "rowtype" type --- either RECORD or a named composite type
2634 : * (including a domain over a named composite type).
2635 : */
2636 : bool
2637 149066 : type_is_rowtype(Oid typid)
2638 : {
2639 149066 : if (typid == RECORDOID)
2640 89522 : return true; /* easy case */
2641 59544 : switch (get_typtype(typid))
2642 : {
2643 3524 : case TYPTYPE_COMPOSITE:
2644 3524 : return true;
2645 260 : case TYPTYPE_DOMAIN:
2646 260 : if (get_typtype(getBaseType(typid)) == TYPTYPE_COMPOSITE)
2647 82 : return true;
2648 178 : break;
2649 55760 : default:
2650 55760 : break;
2651 : }
2652 55938 : return false;
2653 : }
2654 :
2655 : /*
2656 : * type_is_enum
2657 : * Returns true if the given type is an enum type.
2658 : */
2659 : bool
2660 78786 : type_is_enum(Oid typid)
2661 : {
2662 78786 : return (get_typtype(typid) == TYPTYPE_ENUM);
2663 : }
2664 :
2665 : /*
2666 : * type_is_range
2667 : * Returns true if the given type is a range type.
2668 : */
2669 : bool
2670 18274 : type_is_range(Oid typid)
2671 : {
2672 18274 : return (get_typtype(typid) == TYPTYPE_RANGE);
2673 : }
2674 :
2675 : /*
2676 : * type_is_multirange
2677 : * Returns true if the given type is a multirange type.
2678 : */
2679 : bool
2680 39336 : type_is_multirange(Oid typid)
2681 : {
2682 39336 : return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
2683 : }
2684 :
2685 : /*
2686 : * get_type_category_preferred
2687 : *
2688 : * Given the type OID, fetch its category and preferred-type status.
2689 : * Throws error on failure.
2690 : */
2691 : void
2692 294536 : get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2693 : {
2694 : HeapTuple tp;
2695 : Form_pg_type typtup;
2696 :
2697 294536 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2698 294536 : if (!HeapTupleIsValid(tp))
2699 0 : elog(ERROR, "cache lookup failed for type %u", typid);
2700 294536 : typtup = (Form_pg_type) GETSTRUCT(tp);
2701 294536 : *typcategory = typtup->typcategory;
2702 294536 : *typispreferred = typtup->typispreferred;
2703 294536 : ReleaseSysCache(tp);
2704 294536 : }
2705 :
2706 : /*
2707 : * get_typ_typrelid
2708 : *
2709 : * Given the type OID, get the typrelid (InvalidOid if not a complex
2710 : * type).
2711 : */
2712 : Oid
2713 9684 : get_typ_typrelid(Oid typid)
2714 : {
2715 : HeapTuple tp;
2716 :
2717 9684 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2718 9684 : if (HeapTupleIsValid(tp))
2719 : {
2720 9684 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2721 : Oid result;
2722 :
2723 9684 : result = typtup->typrelid;
2724 9684 : ReleaseSysCache(tp);
2725 9684 : return result;
2726 : }
2727 : else
2728 0 : return InvalidOid;
2729 : }
2730 :
2731 : /*
2732 : * get_element_type
2733 : *
2734 : * Given the type OID, get the typelem (InvalidOid if not an array type).
2735 : *
2736 : * NB: this only succeeds for "true" arrays having array_subscript_handler
2737 : * as typsubscript. For other types, InvalidOid is returned independently
2738 : * of whether they have typelem or typsubscript set.
2739 : */
2740 : Oid
2741 1104022 : get_element_type(Oid typid)
2742 : {
2743 : HeapTuple tp;
2744 :
2745 1104022 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2746 1104022 : if (HeapTupleIsValid(tp))
2747 : {
2748 1103988 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2749 : Oid result;
2750 :
2751 1103988 : if (IsTrueArrayType(typtup))
2752 97484 : result = typtup->typelem;
2753 : else
2754 1006504 : result = InvalidOid;
2755 1103988 : ReleaseSysCache(tp);
2756 1103988 : return result;
2757 : }
2758 : else
2759 34 : return InvalidOid;
2760 : }
2761 :
2762 : /*
2763 : * get_array_type
2764 : *
2765 : * Given the type OID, get the corresponding "true" array type.
2766 : * Returns InvalidOid if no array type can be found.
2767 : */
2768 : Oid
2769 90110 : get_array_type(Oid typid)
2770 : {
2771 : HeapTuple tp;
2772 90110 : Oid result = InvalidOid;
2773 :
2774 90110 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2775 90110 : if (HeapTupleIsValid(tp))
2776 : {
2777 90110 : result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2778 90110 : ReleaseSysCache(tp);
2779 : }
2780 90110 : return result;
2781 : }
2782 :
2783 : /*
2784 : * get_promoted_array_type
2785 : *
2786 : * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
2787 : * construct, that is, either the corresponding "true" array type
2788 : * if the input is a scalar type that has such an array type,
2789 : * or the same type if the input is already a "true" array type.
2790 : * Returns InvalidOid if neither rule is satisfied.
2791 : */
2792 : Oid
2793 14706 : get_promoted_array_type(Oid typid)
2794 : {
2795 14706 : Oid array_type = get_array_type(typid);
2796 :
2797 14706 : if (OidIsValid(array_type))
2798 14670 : return array_type;
2799 36 : if (OidIsValid(get_element_type(typid)))
2800 36 : return typid;
2801 0 : return InvalidOid;
2802 : }
2803 :
2804 : /*
2805 : * get_base_element_type
2806 : * Given the type OID, get the typelem, looking "through" any domain
2807 : * to its underlying array type.
2808 : *
2809 : * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2810 : * an extra cache lookup. Note that it fails to provide any information
2811 : * about the typmod of the array.
2812 : */
2813 : Oid
2814 210670 : get_base_element_type(Oid typid)
2815 : {
2816 : /*
2817 : * We loop to find the bottom base type in a stack of domains.
2818 : */
2819 : for (;;)
2820 66 : {
2821 : HeapTuple tup;
2822 : Form_pg_type typTup;
2823 :
2824 210670 : tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2825 210670 : if (!HeapTupleIsValid(tup))
2826 206 : break;
2827 210464 : typTup = (Form_pg_type) GETSTRUCT(tup);
2828 210464 : if (typTup->typtype != TYPTYPE_DOMAIN)
2829 : {
2830 : /* Not a domain, so stop descending */
2831 : Oid result;
2832 :
2833 : /* This test must match get_element_type */
2834 210398 : if (IsTrueArrayType(typTup))
2835 52912 : result = typTup->typelem;
2836 : else
2837 157486 : result = InvalidOid;
2838 210398 : ReleaseSysCache(tup);
2839 210398 : return result;
2840 : }
2841 :
2842 66 : typid = typTup->typbasetype;
2843 66 : ReleaseSysCache(tup);
2844 : }
2845 :
2846 : /* Like get_element_type, silently return InvalidOid for bogus input */
2847 206 : return InvalidOid;
2848 : }
2849 :
2850 : /*
2851 : * getTypeInputInfo
2852 : *
2853 : * Get info needed for converting values of a type to internal form
2854 : */
2855 : void
2856 607916 : getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2857 : {
2858 : HeapTuple typeTuple;
2859 : Form_pg_type pt;
2860 :
2861 607916 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2862 607916 : if (!HeapTupleIsValid(typeTuple))
2863 0 : elog(ERROR, "cache lookup failed for type %u", type);
2864 607916 : pt = (Form_pg_type) GETSTRUCT(typeTuple);
2865 :
2866 607916 : if (!pt->typisdefined)
2867 0 : ereport(ERROR,
2868 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2869 : errmsg("type %s is only a shell",
2870 : format_type_be(type))));
2871 607916 : if (!OidIsValid(pt->typinput))
2872 0 : ereport(ERROR,
2873 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2874 : errmsg("no input function available for type %s",
2875 : format_type_be(type))));
2876 :
2877 607916 : *typInput = pt->typinput;
2878 607916 : *typIOParam = getTypeIOParam(typeTuple);
2879 :
2880 607916 : ReleaseSysCache(typeTuple);
2881 607916 : }
2882 :
2883 : /*
2884 : * getTypeOutputInfo
2885 : *
2886 : * Get info needed for printing values of a type
2887 : */
2888 : void
2889 1444562 : getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2890 : {
2891 : HeapTuple typeTuple;
2892 : Form_pg_type pt;
2893 :
2894 1444562 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2895 1444562 : if (!HeapTupleIsValid(typeTuple))
2896 0 : elog(ERROR, "cache lookup failed for type %u", type);
2897 1444562 : pt = (Form_pg_type) GETSTRUCT(typeTuple);
2898 :
2899 1444562 : if (!pt->typisdefined)
2900 0 : ereport(ERROR,
2901 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2902 : errmsg("type %s is only a shell",
2903 : format_type_be(type))));
2904 1444562 : if (!OidIsValid(pt->typoutput))
2905 0 : ereport(ERROR,
2906 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2907 : errmsg("no output function available for type %s",
2908 : format_type_be(type))));
2909 :
2910 1444562 : *typOutput = pt->typoutput;
2911 1444562 : *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2912 :
2913 1444562 : ReleaseSysCache(typeTuple);
2914 1444562 : }
2915 :
2916 : /*
2917 : * getTypeBinaryInputInfo
2918 : *
2919 : * Get info needed for binary input of values of a type
2920 : */
2921 : void
2922 313864 : getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2923 : {
2924 : HeapTuple typeTuple;
2925 : Form_pg_type pt;
2926 :
2927 313864 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2928 313864 : if (!HeapTupleIsValid(typeTuple))
2929 0 : elog(ERROR, "cache lookup failed for type %u", type);
2930 313864 : pt = (Form_pg_type) GETSTRUCT(typeTuple);
2931 :
2932 313864 : if (!pt->typisdefined)
2933 0 : ereport(ERROR,
2934 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2935 : errmsg("type %s is only a shell",
2936 : format_type_be(type))));
2937 313864 : if (!OidIsValid(pt->typreceive))
2938 2 : ereport(ERROR,
2939 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2940 : errmsg("no binary input function available for type %s",
2941 : format_type_be(type))));
2942 :
2943 313862 : *typReceive = pt->typreceive;
2944 313862 : *typIOParam = getTypeIOParam(typeTuple);
2945 :
2946 313862 : ReleaseSysCache(typeTuple);
2947 313862 : }
2948 :
2949 : /*
2950 : * getTypeBinaryOutputInfo
2951 : *
2952 : * Get info needed for binary output of values of a type
2953 : */
2954 : void
2955 2232 : getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2956 : {
2957 : HeapTuple typeTuple;
2958 : Form_pg_type pt;
2959 :
2960 2232 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2961 2232 : if (!HeapTupleIsValid(typeTuple))
2962 0 : elog(ERROR, "cache lookup failed for type %u", type);
2963 2232 : pt = (Form_pg_type) GETSTRUCT(typeTuple);
2964 :
2965 2232 : if (!pt->typisdefined)
2966 0 : ereport(ERROR,
2967 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2968 : errmsg("type %s is only a shell",
2969 : format_type_be(type))));
2970 2232 : if (!OidIsValid(pt->typsend))
2971 2 : ereport(ERROR,
2972 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2973 : errmsg("no binary output function available for type %s",
2974 : format_type_be(type))));
2975 :
2976 2230 : *typSend = pt->typsend;
2977 2230 : *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2978 :
2979 2230 : ReleaseSysCache(typeTuple);
2980 2230 : }
2981 :
2982 : /*
2983 : * get_typmodin
2984 : *
2985 : * Given the type OID, return the type's typmodin procedure, if any.
2986 : */
2987 : Oid
2988 0 : get_typmodin(Oid typid)
2989 : {
2990 : HeapTuple tp;
2991 :
2992 0 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2993 0 : if (HeapTupleIsValid(tp))
2994 : {
2995 0 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2996 : Oid result;
2997 :
2998 0 : result = typtup->typmodin;
2999 0 : ReleaseSysCache(tp);
3000 0 : return result;
3001 : }
3002 : else
3003 0 : return InvalidOid;
3004 : }
3005 :
3006 : #ifdef NOT_USED
3007 : /*
3008 : * get_typmodout
3009 : *
3010 : * Given the type OID, return the type's typmodout procedure, if any.
3011 : */
3012 : Oid
3013 : get_typmodout(Oid typid)
3014 : {
3015 : HeapTuple tp;
3016 :
3017 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3018 : if (HeapTupleIsValid(tp))
3019 : {
3020 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
3021 : Oid result;
3022 :
3023 : result = typtup->typmodout;
3024 : ReleaseSysCache(tp);
3025 : return result;
3026 : }
3027 : else
3028 : return InvalidOid;
3029 : }
3030 : #endif /* NOT_USED */
3031 :
3032 : /*
3033 : * get_typcollation
3034 : *
3035 : * Given the type OID, return the type's typcollation attribute.
3036 : */
3037 : Oid
3038 2305286 : get_typcollation(Oid typid)
3039 : {
3040 : HeapTuple tp;
3041 :
3042 2305286 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3043 2305286 : if (HeapTupleIsValid(tp))
3044 : {
3045 2305270 : Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
3046 : Oid result;
3047 :
3048 2305270 : result = typtup->typcollation;
3049 2305270 : ReleaseSysCache(tp);
3050 2305270 : return result;
3051 : }
3052 : else
3053 16 : return InvalidOid;
3054 : }
3055 :
3056 :
3057 : /*
3058 : * type_is_collatable
3059 : *
3060 : * Return whether the type cares about collations
3061 : */
3062 : bool
3063 352718 : type_is_collatable(Oid typid)
3064 : {
3065 352718 : return OidIsValid(get_typcollation(typid));
3066 : }
3067 :
3068 :
3069 : /*
3070 : * get_typsubscript
3071 : *
3072 : * Given the type OID, return the type's subscripting handler's OID,
3073 : * if it has one.
3074 : *
3075 : * If typelemp isn't NULL, we also store the type's typelem value there.
3076 : * This saves some callers an extra catalog lookup.
3077 : */
3078 : RegProcedure
3079 31690 : get_typsubscript(Oid typid, Oid *typelemp)
3080 : {
3081 : HeapTuple tp;
3082 :
3083 31690 : tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3084 31690 : if (HeapTupleIsValid(tp))
3085 : {
3086 31690 : Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
3087 31690 : RegProcedure handler = typform->typsubscript;
3088 :
3089 31690 : if (typelemp)
3090 10452 : *typelemp = typform->typelem;
3091 31690 : ReleaseSysCache(tp);
3092 31690 : return handler;
3093 : }
3094 : else
3095 : {
3096 0 : if (typelemp)
3097 0 : *typelemp = InvalidOid;
3098 0 : return InvalidOid;
3099 : }
3100 : }
3101 :
3102 : /*
3103 : * getSubscriptingRoutines
3104 : *
3105 : * Given the type OID, fetch the type's subscripting methods struct.
3106 : * Return NULL if type is not subscriptable.
3107 : *
3108 : * If typelemp isn't NULL, we also store the type's typelem value there.
3109 : * This saves some callers an extra catalog lookup.
3110 : */
3111 : const struct SubscriptRoutines *
3112 31630 : getSubscriptingRoutines(Oid typid, Oid *typelemp)
3113 : {
3114 31630 : RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3115 :
3116 31630 : if (!OidIsValid(typsubscript))
3117 10 : return NULL;
3118 :
3119 31620 : return (const struct SubscriptRoutines *)
3120 31620 : DatumGetPointer(OidFunctionCall0(typsubscript));
3121 : }
3122 :
3123 :
3124 : /* ---------- STATISTICS CACHE ---------- */
3125 :
3126 : /*
3127 : * get_attavgwidth
3128 : *
3129 : * Given the table and attribute number of a column, get the average
3130 : * width of entries in the column. Return zero if no data available.
3131 : *
3132 : * Currently this is only consulted for individual tables, not for inheritance
3133 : * trees, so we don't need an "inh" parameter.
3134 : *
3135 : * Calling a hook at this point looks somewhat strange, but is required
3136 : * because the optimizer calls this function without any other way for
3137 : * plug-ins to control the result.
3138 : */
3139 : int32
3140 1000214 : get_attavgwidth(Oid relid, AttrNumber attnum)
3141 : {
3142 : HeapTuple tp;
3143 : int32 stawidth;
3144 :
3145 1000214 : if (get_attavgwidth_hook)
3146 : {
3147 0 : stawidth = (*get_attavgwidth_hook) (relid, attnum);
3148 0 : if (stawidth > 0)
3149 0 : return stawidth;
3150 : }
3151 1000214 : tp = SearchSysCache3(STATRELATTINH,
3152 : ObjectIdGetDatum(relid),
3153 : Int16GetDatum(attnum),
3154 : BoolGetDatum(false));
3155 1000214 : if (HeapTupleIsValid(tp))
3156 : {
3157 533422 : stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3158 533422 : ReleaseSysCache(tp);
3159 533422 : if (stawidth > 0)
3160 521678 : return stawidth;
3161 : }
3162 478536 : return 0;
3163 : }
3164 :
3165 : /*
3166 : * get_attstatsslot
3167 : *
3168 : * Extract the contents of a "slot" of a pg_statistic tuple.
3169 : * Returns true if requested slot type was found, else false.
3170 : *
3171 : * Unlike other routines in this file, this takes a pointer to an
3172 : * already-looked-up tuple in the pg_statistic cache. We do this since
3173 : * most callers will want to extract more than one value from the cache
3174 : * entry, and we don't want to repeat the cache lookup unnecessarily.
3175 : * Also, this API allows this routine to be used with statistics tuples
3176 : * that have been provided by a stats hook and didn't really come from
3177 : * pg_statistic.
3178 : *
3179 : * sslot: pointer to output area (typically, a local variable in the caller).
3180 : * statstuple: pg_statistic tuple to be examined.
3181 : * reqkind: STAKIND code for desired statistics slot kind.
3182 : * reqop: STAOP value wanted, or InvalidOid if don't care.
3183 : * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3184 : *
3185 : * If a matching slot is found, true is returned, and *sslot is filled thus:
3186 : * staop: receives the actual STAOP value.
3187 : * stacoll: receives the actual STACOLL value.
3188 : * valuetype: receives actual datatype of the elements of stavalues.
3189 : * values: receives pointer to an array of the slot's stavalues.
3190 : * nvalues: receives number of stavalues.
3191 : * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3192 : * nnumbers: receives number of stanumbers.
3193 : *
3194 : * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3195 : * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3196 : * ATTSTATSSLOT_NUMBERS wasn't specified.
3197 : *
3198 : * If no matching slot is found, false is returned, and *sslot is zeroed.
3199 : *
3200 : * Note that the current API doesn't allow for searching for a slot with
3201 : * a particular collation. If we ever actually support recording more than
3202 : * one collation, we'll have to extend the API, but for now simple is good.
3203 : *
3204 : * The data referred to by the fields of sslot is locally palloc'd and
3205 : * is independent of the original pg_statistic tuple. When the caller
3206 : * is done with it, call free_attstatsslot to release the palloc'd data.
3207 : *
3208 : * If it's desirable to call free_attstatsslot when get_attstatsslot might
3209 : * not have been called, memset'ing sslot to zeroes will allow that.
3210 : *
3211 : * Passing flags=0 can be useful to quickly check if the requested slot type
3212 : * exists. In this case no arrays are extracted, so free_attstatsslot need
3213 : * not be called.
3214 : */
3215 : bool
3216 1771028 : get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
3217 : int reqkind, Oid reqop, int flags)
3218 : {
3219 1771028 : Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
3220 : int i;
3221 : Datum val;
3222 : ArrayType *statarray;
3223 : Oid arrayelemtype;
3224 : int narrayelem;
3225 : HeapTuple typeTuple;
3226 : Form_pg_type typeForm;
3227 :
3228 : /* initialize *sslot properly */
3229 1771028 : memset(sslot, 0, sizeof(AttStatsSlot));
3230 :
3231 4922762 : for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3232 : {
3233 4418136 : if ((&stats->stakind1)[i] == reqkind &&
3234 540140 : (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3235 : break;
3236 : }
3237 1771028 : if (i >= STATISTIC_NUM_SLOTS)
3238 504626 : return false; /* not there */
3239 :
3240 1266402 : sslot->staop = (&stats->staop1)[i];
3241 1266402 : sslot->stacoll = (&stats->stacoll1)[i];
3242 :
3243 1266402 : if (flags & ATTSTATSSLOT_VALUES)
3244 : {
3245 626410 : val = SysCacheGetAttrNotNull(STATRELATTINH, statstuple,
3246 626410 : Anum_pg_statistic_stavalues1 + i);
3247 :
3248 : /*
3249 : * Detoast the array if needed, and in any case make a copy that's
3250 : * under control of this AttStatsSlot.
3251 : */
3252 626410 : statarray = DatumGetArrayTypePCopy(val);
3253 :
3254 : /*
3255 : * Extract the actual array element type, and pass it back in case the
3256 : * caller needs it.
3257 : */
3258 626410 : sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3259 :
3260 : /* Need info about element type */
3261 626410 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
3262 626410 : if (!HeapTupleIsValid(typeTuple))
3263 0 : elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3264 626410 : typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
3265 :
3266 : /* Deconstruct array into Datum elements; NULLs not expected */
3267 626410 : deconstruct_array(statarray,
3268 : arrayelemtype,
3269 626410 : typeForm->typlen,
3270 626410 : typeForm->typbyval,
3271 626410 : typeForm->typalign,
3272 : &sslot->values, NULL, &sslot->nvalues);
3273 :
3274 : /*
3275 : * If the element type is pass-by-reference, we now have a bunch of
3276 : * Datums that are pointers into the statarray, so we need to keep
3277 : * that until free_attstatsslot. Otherwise, all the useful info is in
3278 : * sslot->values[], so we can free the array object immediately.
3279 : */
3280 626410 : if (!typeForm->typbyval)
3281 39530 : sslot->values_arr = statarray;
3282 : else
3283 586880 : pfree(statarray);
3284 :
3285 626410 : ReleaseSysCache(typeTuple);
3286 : }
3287 :
3288 1266402 : if (flags & ATTSTATSSLOT_NUMBERS)
3289 : {
3290 871624 : val = SysCacheGetAttrNotNull(STATRELATTINH, statstuple,
3291 871624 : Anum_pg_statistic_stanumbers1 + i);
3292 :
3293 : /*
3294 : * Detoast the array if needed, and in any case make a copy that's
3295 : * under control of this AttStatsSlot.
3296 : */
3297 871624 : statarray = DatumGetArrayTypePCopy(val);
3298 :
3299 : /*
3300 : * We expect the array to be a 1-D float4 array; verify that. We don't
3301 : * need to use deconstruct_array() since the array data is just going
3302 : * to look like a C array of float4 values.
3303 : */
3304 871624 : narrayelem = ARR_DIMS(statarray)[0];
3305 871624 : if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3306 871624 : ARR_HASNULL(statarray) ||
3307 871624 : ARR_ELEMTYPE(statarray) != FLOAT4OID)
3308 0 : elog(ERROR, "stanumbers is not a 1-D float4 array");
3309 :
3310 : /* Give caller a pointer directly into the statarray */
3311 871624 : sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3312 871624 : sslot->nnumbers = narrayelem;
3313 :
3314 : /* We'll free the statarray in free_attstatsslot */
3315 871624 : sslot->numbers_arr = statarray;
3316 : }
3317 :
3318 1266402 : return true;
3319 : }
3320 :
3321 : /*
3322 : * free_attstatsslot
3323 : * Free data allocated by get_attstatsslot
3324 : */
3325 : void
3326 1538892 : free_attstatsslot(AttStatsSlot *sslot)
3327 : {
3328 : /* The values[] array was separately palloc'd by deconstruct_array */
3329 1538892 : if (sslot->values)
3330 626410 : pfree(sslot->values);
3331 : /* The numbers[] array points into numbers_arr, do not pfree it */
3332 : /* Free the detoasted array objects, if any */
3333 1538892 : if (sslot->values_arr)
3334 39530 : pfree(sslot->values_arr);
3335 1538892 : if (sslot->numbers_arr)
3336 871624 : pfree(sslot->numbers_arr);
3337 1538892 : }
3338 :
3339 : /* ---------- PG_NAMESPACE CACHE ---------- */
3340 :
3341 : /*
3342 : * get_namespace_name
3343 : * Returns the name of a given namespace
3344 : *
3345 : * Returns a palloc'd copy of the string, or NULL if no such namespace.
3346 : */
3347 : char *
3348 612806 : get_namespace_name(Oid nspid)
3349 : {
3350 : HeapTuple tp;
3351 :
3352 612806 : tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
3353 612806 : if (HeapTupleIsValid(tp))
3354 : {
3355 612788 : Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
3356 : char *result;
3357 :
3358 612788 : result = pstrdup(NameStr(nsptup->nspname));
3359 612788 : ReleaseSysCache(tp);
3360 612788 : return result;
3361 : }
3362 : else
3363 18 : return NULL;
3364 : }
3365 :
3366 : /*
3367 : * get_namespace_name_or_temp
3368 : * As above, but if it is this backend's temporary namespace, return
3369 : * "pg_temp" instead.
3370 : */
3371 : char *
3372 29268 : get_namespace_name_or_temp(Oid nspid)
3373 : {
3374 29268 : if (isTempNamespace(nspid))
3375 116 : return pstrdup("pg_temp");
3376 : else
3377 29152 : return get_namespace_name(nspid);
3378 : }
3379 :
3380 : /* ---------- PG_RANGE CACHES ---------- */
3381 :
3382 : /*
3383 : * get_range_subtype
3384 : * Returns the subtype of a given range type
3385 : *
3386 : * Returns InvalidOid if the type is not a range type.
3387 : */
3388 : Oid
3389 13912 : get_range_subtype(Oid rangeOid)
3390 : {
3391 : HeapTuple tp;
3392 :
3393 13912 : tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3394 13912 : if (HeapTupleIsValid(tp))
3395 : {
3396 9252 : Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3397 : Oid result;
3398 :
3399 9252 : result = rngtup->rngsubtype;
3400 9252 : ReleaseSysCache(tp);
3401 9252 : return result;
3402 : }
3403 : else
3404 4660 : return InvalidOid;
3405 : }
3406 :
3407 : /*
3408 : * get_range_collation
3409 : * Returns the collation of a given range type
3410 : *
3411 : * Returns InvalidOid if the type is not a range type,
3412 : * or if its subtype is not collatable.
3413 : */
3414 : Oid
3415 548 : get_range_collation(Oid rangeOid)
3416 : {
3417 : HeapTuple tp;
3418 :
3419 548 : tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3420 548 : if (HeapTupleIsValid(tp))
3421 : {
3422 548 : Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3423 : Oid result;
3424 :
3425 548 : result = rngtup->rngcollation;
3426 548 : ReleaseSysCache(tp);
3427 548 : return result;
3428 : }
3429 : else
3430 0 : return InvalidOid;
3431 : }
3432 :
3433 : /*
3434 : * get_range_multirange
3435 : * Returns the multirange type of a given range type
3436 : *
3437 : * Returns InvalidOid if the type is not a range type.
3438 : */
3439 : Oid
3440 174 : get_range_multirange(Oid rangeOid)
3441 : {
3442 : HeapTuple tp;
3443 :
3444 174 : tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3445 174 : if (HeapTupleIsValid(tp))
3446 : {
3447 174 : Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3448 : Oid result;
3449 :
3450 174 : result = rngtup->rngmultitypid;
3451 174 : ReleaseSysCache(tp);
3452 174 : return result;
3453 : }
3454 : else
3455 0 : return InvalidOid;
3456 : }
3457 :
3458 : /*
3459 : * get_multirange_range
3460 : * Returns the range type of a given multirange
3461 : *
3462 : * Returns InvalidOid if the type is not a multirange.
3463 : */
3464 : Oid
3465 16374 : get_multirange_range(Oid multirangeOid)
3466 : {
3467 : HeapTuple tp;
3468 :
3469 16374 : tp = SearchSysCache1(RANGEMULTIRANGE, ObjectIdGetDatum(multirangeOid));
3470 16374 : if (HeapTupleIsValid(tp))
3471 : {
3472 4656 : Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3473 : Oid result;
3474 :
3475 4656 : result = rngtup->rngtypid;
3476 4656 : ReleaseSysCache(tp);
3477 4656 : return result;
3478 : }
3479 : else
3480 11718 : return InvalidOid;
3481 : }
3482 :
3483 : /* ---------- PG_INDEX CACHE ---------- */
3484 :
3485 : /*
3486 : * get_index_column_opclass
3487 : *
3488 : * Given the index OID and column number,
3489 : * return opclass of the index column
3490 : * or InvalidOid if the index was not found
3491 : * or column is non-key one.
3492 : */
3493 : Oid
3494 36 : get_index_column_opclass(Oid index_oid, int attno)
3495 : {
3496 : HeapTuple tuple;
3497 : Form_pg_index rd_index;
3498 : Datum datum;
3499 : oidvector *indclass;
3500 : Oid opclass;
3501 :
3502 : /* First we need to know the column's opclass. */
3503 :
3504 36 : tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3505 36 : if (!HeapTupleIsValid(tuple))
3506 0 : return InvalidOid;
3507 :
3508 36 : rd_index = (Form_pg_index) GETSTRUCT(tuple);
3509 :
3510 : /* caller is supposed to guarantee this */
3511 : Assert(attno > 0 && attno <= rd_index->indnatts);
3512 :
3513 : /* Non-key attributes don't have an opclass */
3514 36 : if (attno > rd_index->indnkeyatts)
3515 : {
3516 0 : ReleaseSysCache(tuple);
3517 0 : return InvalidOid;
3518 : }
3519 :
3520 36 : datum = SysCacheGetAttrNotNull(INDEXRELID, tuple, Anum_pg_index_indclass);
3521 36 : indclass = ((oidvector *) DatumGetPointer(datum));
3522 :
3523 : Assert(attno <= indclass->dim1);
3524 36 : opclass = indclass->values[attno - 1];
3525 :
3526 36 : ReleaseSysCache(tuple);
3527 :
3528 36 : return opclass;
3529 : }
3530 :
3531 : /*
3532 : * get_index_isreplident
3533 : *
3534 : * Given the index OID, return pg_index.indisreplident.
3535 : */
3536 : bool
3537 398 : get_index_isreplident(Oid index_oid)
3538 : {
3539 : HeapTuple tuple;
3540 : Form_pg_index rd_index;
3541 : bool result;
3542 :
3543 398 : tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3544 398 : if (!HeapTupleIsValid(tuple))
3545 0 : return false;
3546 :
3547 398 : rd_index = (Form_pg_index) GETSTRUCT(tuple);
3548 398 : result = rd_index->indisreplident;
3549 398 : ReleaseSysCache(tuple);
3550 :
3551 398 : return result;
3552 : }
3553 :
3554 : /*
3555 : * get_index_isvalid
3556 : *
3557 : * Given the index OID, return pg_index.indisvalid.
3558 : */
3559 : bool
3560 4430 : get_index_isvalid(Oid index_oid)
3561 : {
3562 : bool isvalid;
3563 : HeapTuple tuple;
3564 : Form_pg_index rd_index;
3565 :
3566 4430 : tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3567 4430 : if (!HeapTupleIsValid(tuple))
3568 0 : elog(ERROR, "cache lookup failed for index %u", index_oid);
3569 :
3570 4430 : rd_index = (Form_pg_index) GETSTRUCT(tuple);
3571 4430 : isvalid = rd_index->indisvalid;
3572 4430 : ReleaseSysCache(tuple);
3573 :
3574 4430 : return isvalid;
3575 : }
3576 :
3577 : /*
3578 : * get_index_isclustered
3579 : *
3580 : * Given the index OID, return pg_index.indisclustered.
3581 : */
3582 : bool
3583 658 : get_index_isclustered(Oid index_oid)
3584 : {
3585 : bool isclustered;
3586 : HeapTuple tuple;
3587 : Form_pg_index rd_index;
3588 :
3589 658 : tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3590 658 : if (!HeapTupleIsValid(tuple))
3591 0 : elog(ERROR, "cache lookup failed for index %u", index_oid);
3592 :
3593 658 : rd_index = (Form_pg_index) GETSTRUCT(tuple);
3594 658 : isclustered = rd_index->indisclustered;
3595 658 : ReleaseSysCache(tuple);
3596 :
3597 658 : return isclustered;
3598 : }
3599 :
3600 : /*
3601 : * get_publication_oid - given a publication name, look up the OID
3602 : *
3603 : * If missing_ok is false, throw an error if name not found. If true, just
3604 : * return InvalidOid.
3605 : */
3606 : Oid
3607 2560 : get_publication_oid(const char *pubname, bool missing_ok)
3608 : {
3609 : Oid oid;
3610 :
3611 2560 : oid = GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
3612 : CStringGetDatum(pubname));
3613 2560 : if (!OidIsValid(oid) && !missing_ok)
3614 8 : ereport(ERROR,
3615 : (errcode(ERRCODE_UNDEFINED_OBJECT),
3616 : errmsg("publication \"%s\" does not exist", pubname)));
3617 2552 : return oid;
3618 : }
3619 :
3620 : /*
3621 : * get_publication_name - given a publication Oid, look up the name
3622 : *
3623 : * If missing_ok is false, throw an error if name not found. If true, just
3624 : * return NULL.
3625 : */
3626 : char *
3627 602 : get_publication_name(Oid pubid, bool missing_ok)
3628 : {
3629 : HeapTuple tup;
3630 : char *pubname;
3631 : Form_pg_publication pubform;
3632 :
3633 602 : tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
3634 :
3635 602 : if (!HeapTupleIsValid(tup))
3636 : {
3637 18 : if (!missing_ok)
3638 0 : elog(ERROR, "cache lookup failed for publication %u", pubid);
3639 18 : return NULL;
3640 : }
3641 :
3642 584 : pubform = (Form_pg_publication) GETSTRUCT(tup);
3643 584 : pubname = pstrdup(NameStr(pubform->pubname));
3644 :
3645 584 : ReleaseSysCache(tup);
3646 :
3647 584 : return pubname;
3648 : }
3649 :
3650 : /*
3651 : * get_subscription_oid - given a subscription name, look up the OID
3652 : *
3653 : * If missing_ok is false, throw an error if name not found. If true, just
3654 : * return InvalidOid.
3655 : */
3656 : Oid
3657 68 : get_subscription_oid(const char *subname, bool missing_ok)
3658 : {
3659 : Oid oid;
3660 :
3661 68 : oid = GetSysCacheOid2(SUBSCRIPTIONNAME, Anum_pg_subscription_oid,
3662 : MyDatabaseId, CStringGetDatum(subname));
3663 68 : if (!OidIsValid(oid) && !missing_ok)
3664 6 : ereport(ERROR,
3665 : (errcode(ERRCODE_UNDEFINED_OBJECT),
3666 : errmsg("subscription \"%s\" does not exist", subname)));
3667 62 : return oid;
3668 : }
3669 :
3670 : /*
3671 : * get_subscription_name - given a subscription OID, look up the name
3672 : *
3673 : * If missing_ok is false, throw an error if name not found. If true, just
3674 : * return NULL.
3675 : */
3676 : char *
3677 60 : get_subscription_name(Oid subid, bool missing_ok)
3678 : {
3679 : HeapTuple tup;
3680 : char *subname;
3681 : Form_pg_subscription subform;
3682 :
3683 60 : tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
3684 :
3685 60 : if (!HeapTupleIsValid(tup))
3686 : {
3687 18 : if (!missing_ok)
3688 0 : elog(ERROR, "cache lookup failed for subscription %u", subid);
3689 18 : return NULL;
3690 : }
3691 :
3692 42 : subform = (Form_pg_subscription) GETSTRUCT(tup);
3693 42 : subname = pstrdup(NameStr(subform->subname));
3694 :
3695 42 : ReleaseSysCache(tup);
3696 :
3697 42 : return subname;
3698 : }
|