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