Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * parse_coerce.c
4 : * handle type coercions/conversions for parser
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/parser/parse_coerce.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/htup_details.h"
18 : #include "catalog/pg_cast.h"
19 : #include "catalog/pg_class.h"
20 : #include "catalog/pg_inherits_fn.h"
21 : #include "catalog/pg_proc.h"
22 : #include "catalog/pg_type.h"
23 : #include "nodes/makefuncs.h"
24 : #include "nodes/nodeFuncs.h"
25 : #include "parser/parse_coerce.h"
26 : #include "parser/parse_relation.h"
27 : #include "parser/parse_type.h"
28 : #include "utils/builtins.h"
29 : #include "utils/datum.h"
30 : #include "utils/lsyscache.h"
31 : #include "utils/syscache.h"
32 : #include "utils/typcache.h"
33 :
34 :
35 : static Node *coerce_type_typmod(Node *node,
36 : Oid targetTypeId, int32 targetTypMod,
37 : CoercionForm cformat, int location,
38 : bool isExplicit, bool hideInputCoercion);
39 : static void hide_coercion_node(Node *node);
40 : static Node *build_coercion_expression(Node *node,
41 : CoercionPathType pathtype,
42 : Oid funcId,
43 : Oid targetTypeId, int32 targetTypMod,
44 : CoercionForm cformat, int location,
45 : bool isExplicit);
46 : static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
47 : Oid targetTypeId,
48 : CoercionContext ccontext,
49 : CoercionForm cformat,
50 : int location);
51 : static bool is_complex_array(Oid typid);
52 : static bool typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId);
53 :
54 :
55 : /*
56 : * coerce_to_target_type()
57 : * Convert an expression to a target type and typmod.
58 : *
59 : * This is the general-purpose entry point for arbitrary type coercion
60 : * operations. Direct use of the component operations can_coerce_type,
61 : * coerce_type, and coerce_type_typmod should be restricted to special
62 : * cases (eg, when the conversion is expected to succeed).
63 : *
64 : * Returns the possibly-transformed expression tree, or NULL if the type
65 : * conversion is not possible. (We do this, rather than ereport'ing directly,
66 : * so that callers can generate custom error messages indicating context.)
67 : *
68 : * pstate - parse state (can be NULL, see coerce_type)
69 : * expr - input expression tree (already transformed by transformExpr)
70 : * exprtype - result type of expr
71 : * targettype - desired result type
72 : * targettypmod - desired result typmod
73 : * ccontext, cformat - context indicators to control coercions
74 : * location - parse location of the coercion request, or -1 if unknown/implicit
75 : */
76 : Node *
77 22179 : coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
78 : Oid targettype, int32 targettypmod,
79 : CoercionContext ccontext,
80 : CoercionForm cformat,
81 : int location)
82 : {
83 : Node *result;
84 : Node *origexpr;
85 :
86 22179 : if (!can_coerce_type(1, &exprtype, &targettype, ccontext))
87 19 : return NULL;
88 :
89 : /*
90 : * If the input has a CollateExpr at the top, strip it off, perform the
91 : * coercion, and put a new one back on. This is annoying since it
92 : * duplicates logic in coerce_type, but if we don't do this then it's too
93 : * hard to tell whether coerce_type actually changed anything, and we
94 : * *must* know that to avoid possibly calling hide_coercion_node on
95 : * something that wasn't generated by coerce_type. Note that if there are
96 : * multiple stacked CollateExprs, we just discard all but the topmost.
97 : */
98 22160 : origexpr = expr;
99 44321 : while (expr && IsA(expr, CollateExpr))
100 1 : expr = (Node *) ((CollateExpr *) expr)->arg;
101 :
102 22160 : result = coerce_type(pstate, expr, exprtype,
103 : targettype, targettypmod,
104 : ccontext, cformat, location);
105 :
106 : /*
107 : * If the target is a fixed-length type, it may need a length coercion as
108 : * well as a type coercion. If we find ourselves adding both, force the
109 : * inner coercion node to implicit display form.
110 : */
111 21779 : result = coerce_type_typmod(result,
112 : targettype, targettypmod,
113 : cformat, location,
114 : (cformat != COERCE_IMPLICIT_CAST),
115 21779 : (result != expr && !IsA(result, Const)));
116 :
117 21779 : if (expr != origexpr)
118 : {
119 : /* Reinstall top CollateExpr */
120 1 : CollateExpr *coll = (CollateExpr *) origexpr;
121 1 : CollateExpr *newcoll = makeNode(CollateExpr);
122 :
123 1 : newcoll->arg = (Expr *) result;
124 1 : newcoll->collOid = coll->collOid;
125 1 : newcoll->location = coll->location;
126 1 : result = (Node *) newcoll;
127 : }
128 :
129 21779 : return result;
130 : }
131 :
132 :
133 : /*
134 : * coerce_type()
135 : * Convert an expression to a different type.
136 : *
137 : * The caller should already have determined that the coercion is possible;
138 : * see can_coerce_type.
139 : *
140 : * Normally, no coercion to a typmod (length) is performed here. The caller
141 : * must call coerce_type_typmod as well, if a typmod constraint is wanted.
142 : * (But if the target type is a domain, it may internally contain a
143 : * typmod constraint, which will be applied inside coerce_to_domain.)
144 : * In some cases pg_cast specifies a type coercion function that also
145 : * applies length conversion, and in those cases only, the result will
146 : * already be properly coerced to the specified typmod.
147 : *
148 : * pstate is only used in the case that we are able to resolve the type of
149 : * a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
150 : * caller does not want type information updated for Params.
151 : *
152 : * Note: this function must not modify the given expression tree, only add
153 : * decoration on top of it. See transformSetOperationTree, for example.
154 : */
155 : Node *
156 46537 : coerce_type(ParseState *pstate, Node *node,
157 : Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
158 : CoercionContext ccontext, CoercionForm cformat, int location)
159 : {
160 : Node *result;
161 : CoercionPathType pathtype;
162 : Oid funcId;
163 :
164 46537 : if (targetTypeId == inputTypeId ||
165 : node == NULL)
166 : {
167 : /* no conversion needed */
168 7429 : return node;
169 : }
170 39108 : if (targetTypeId == ANYOID ||
171 37820 : targetTypeId == ANYELEMENTOID ||
172 : targetTypeId == ANYNONARRAYOID)
173 : {
174 : /*
175 : * Assume can_coerce_type verified that implicit coercion is okay.
176 : *
177 : * Note: by returning the unmodified node here, we are saying that
178 : * it's OK to treat an UNKNOWN constant as a valid input for a
179 : * function accepting ANY, ANYELEMENT, or ANYNONARRAY. This should be
180 : * all right, since an UNKNOWN value is still a perfectly valid Datum.
181 : *
182 : * NB: we do NOT want a RelabelType here: the exposed type of the
183 : * function argument must be its actual type, not the polymorphic
184 : * pseudotype.
185 : */
186 2361 : return node;
187 : }
188 36747 : if (targetTypeId == ANYARRAYOID ||
189 34503 : targetTypeId == ANYENUMOID ||
190 : targetTypeId == ANYRANGEOID)
191 : {
192 : /*
193 : * Assume can_coerce_type verified that implicit coercion is okay.
194 : *
195 : * These cases are unlike the ones above because the exposed type of
196 : * the argument must be an actual array, enum, or range type. In
197 : * particular the argument must *not* be an UNKNOWN constant. If it
198 : * is, we just fall through; below, we'll call anyarray_in,
199 : * anyenum_in, or anyrange_in, which will produce an error. Also, if
200 : * what we have is a domain over array, enum, or range, we have to
201 : * relabel it to its base type.
202 : *
203 : * Note: currently, we can't actually see a domain-over-enum here,
204 : * since the other functions in this file will not match such a
205 : * parameter to ANYENUM. But that should get changed eventually.
206 : */
207 2659 : if (inputTypeId != UNKNOWNOID)
208 : {
209 2656 : Oid baseTypeId = getBaseType(inputTypeId);
210 :
211 2656 : if (baseTypeId != inputTypeId)
212 : {
213 10 : RelabelType *r = makeRelabelType((Expr *) node,
214 : baseTypeId, -1,
215 : InvalidOid,
216 : cformat);
217 :
218 10 : r->location = location;
219 10 : return (Node *) r;
220 : }
221 : /* Not a domain type, so return it as-is */
222 2646 : return node;
223 : }
224 : }
225 34091 : if (inputTypeId == UNKNOWNOID && IsA(node, Const))
226 : {
227 : /*
228 : * Input is a string constant with previously undetermined type. Apply
229 : * the target type's typinput function to it to produce a constant of
230 : * the target type.
231 : *
232 : * NOTE: this case cannot be folded together with the other
233 : * constant-input case, since the typinput function does not
234 : * necessarily behave the same as a type conversion function. For
235 : * example, int4's typinput function will reject "1.2", whereas
236 : * float-to-int type conversion will round to integer.
237 : *
238 : * XXX if the typinput function is not immutable, we really ought to
239 : * postpone evaluation of the function call until runtime. But there
240 : * is no way to represent a typinput function call as an expression
241 : * tree, because C-string values are not Datums. (XXX This *is*
242 : * possible as of 7.3, do we want to do it?)
243 : */
244 26062 : Const *con = (Const *) node;
245 26062 : Const *newcon = makeNode(Const);
246 : Oid baseTypeId;
247 : int32 baseTypeMod;
248 : int32 inputTypeMod;
249 : Type baseType;
250 : ParseCallbackState pcbstate;
251 :
252 : /*
253 : * If the target type is a domain, we want to call its base type's
254 : * input routine, not domain_in(). This is to avoid premature failure
255 : * when the domain applies a typmod: existing input routines follow
256 : * implicit-coercion semantics for length checks, which is not always
257 : * what we want here. The needed check will be applied properly
258 : * inside coerce_to_domain().
259 : */
260 26062 : baseTypeMod = targetTypeMod;
261 26062 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
262 :
263 : /*
264 : * For most types we pass typmod -1 to the input routine, because
265 : * existing input routines follow implicit-coercion semantics for
266 : * length checks, which is not always what we want here. Any length
267 : * constraint will be applied later by our caller. An exception
268 : * however is the INTERVAL type, for which we *must* pass the typmod
269 : * or it won't be able to obey the bizarre SQL-spec input rules. (Ugly
270 : * as sin, but so is this part of the spec...)
271 : */
272 26062 : if (baseTypeId == INTERVALOID)
273 260 : inputTypeMod = baseTypeMod;
274 : else
275 25802 : inputTypeMod = -1;
276 :
277 26062 : baseType = typeidType(baseTypeId);
278 :
279 26062 : newcon->consttype = baseTypeId;
280 26062 : newcon->consttypmod = inputTypeMod;
281 26062 : newcon->constcollid = typeTypeCollation(baseType);
282 26062 : newcon->constlen = typeLen(baseType);
283 26062 : newcon->constbyval = typeByVal(baseType);
284 26062 : newcon->constisnull = con->constisnull;
285 :
286 : /*
287 : * We use the original literal's location regardless of the position
288 : * of the coercion. This is a change from pre-9.2 behavior, meant to
289 : * simplify life for pg_stat_statements.
290 : */
291 26062 : newcon->location = con->location;
292 :
293 : /*
294 : * Set up to point at the constant's text if the input routine throws
295 : * an error.
296 : */
297 26062 : setup_parser_errposition_callback(&pcbstate, pstate, con->location);
298 :
299 : /*
300 : * We assume here that UNKNOWN's internal representation is the same
301 : * as CSTRING.
302 : */
303 26062 : if (!con->constisnull)
304 23951 : newcon->constvalue = stringTypeDatum(baseType,
305 23951 : DatumGetCString(con->constvalue),
306 : inputTypeMod);
307 : else
308 2111 : newcon->constvalue = stringTypeDatum(baseType,
309 : NULL,
310 : inputTypeMod);
311 :
312 : /*
313 : * If it's a varlena value, force it to be in non-expanded
314 : * (non-toasted) format; this avoids any possible dependency on
315 : * external values and improves consistency of representation.
316 : */
317 25636 : if (!con->constisnull && newcon->constlen == -1)
318 14454 : newcon->constvalue =
319 14454 : PointerGetDatum(PG_DETOAST_DATUM(newcon->constvalue));
320 :
321 : #ifdef RANDOMIZE_ALLOCATED_MEMORY
322 :
323 : /*
324 : * For pass-by-reference data types, repeat the conversion to see if
325 : * the input function leaves any uninitialized bytes in the result. We
326 : * can only detect that reliably if RANDOMIZE_ALLOCATED_MEMORY is
327 : * enabled, so we don't bother testing otherwise. The reason we don't
328 : * want any instability in the input function is that comparison of
329 : * Const nodes relies on bytewise comparison of the datums, so if the
330 : * input function leaves garbage then subexpressions that should be
331 : * identical may not get recognized as such. See pgsql-hackers
332 : * discussion of 2008-04-04.
333 : */
334 : if (!con->constisnull && !newcon->constbyval)
335 : {
336 : Datum val2;
337 :
338 : val2 = stringTypeDatum(baseType,
339 : DatumGetCString(con->constvalue),
340 : inputTypeMod);
341 : if (newcon->constlen == -1)
342 : val2 = PointerGetDatum(PG_DETOAST_DATUM(val2));
343 : if (!datumIsEqual(newcon->constvalue, val2, false, newcon->constlen))
344 : elog(WARNING, "type %s has unstable input conversion for \"%s\"",
345 : typeTypeName(baseType), DatumGetCString(con->constvalue));
346 : }
347 : #endif
348 :
349 25636 : cancel_parser_errposition_callback(&pcbstate);
350 :
351 25636 : result = (Node *) newcon;
352 :
353 : /* If target is a domain, apply constraints. */
354 25636 : if (baseTypeId != targetTypeId)
355 527 : result = coerce_to_domain(result,
356 : baseTypeId, baseTypeMod,
357 : targetTypeId,
358 : cformat, location, false, false);
359 :
360 25636 : ReleaseSysCache(baseType);
361 :
362 25636 : return result;
363 : }
364 8029 : if (IsA(node, Param) &&
365 249 : pstate != NULL && pstate->p_coerce_param_hook != NULL)
366 : {
367 : /*
368 : * Allow the CoerceParamHook to decide what happens. It can return a
369 : * transformed node (very possibly the same Param node), or return
370 : * NULL to indicate we should proceed with normal coercion.
371 : */
372 7 : result = (*pstate->p_coerce_param_hook) (pstate,
373 : (Param *) node,
374 : targetTypeId,
375 : targetTypeMod,
376 : location);
377 7 : if (result)
378 4 : return result;
379 : }
380 8025 : if (IsA(node, CollateExpr))
381 : {
382 : /*
383 : * If we have a COLLATE clause, we have to push the coercion
384 : * underneath the COLLATE. This is really ugly, but there is little
385 : * choice because the above hacks on Consts and Params wouldn't happen
386 : * otherwise. This kluge has consequences in coerce_to_target_type.
387 : */
388 9 : CollateExpr *coll = (CollateExpr *) node;
389 9 : CollateExpr *newcoll = makeNode(CollateExpr);
390 :
391 9 : newcoll->arg = (Expr *)
392 9 : coerce_type(pstate, (Node *) coll->arg,
393 : inputTypeId, targetTypeId, targetTypeMod,
394 : ccontext, cformat, location);
395 9 : newcoll->collOid = coll->collOid;
396 9 : newcoll->location = coll->location;
397 9 : return (Node *) newcoll;
398 : }
399 8016 : pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
400 : &funcId);
401 8016 : if (pathtype != COERCION_PATH_NONE)
402 : {
403 7830 : if (pathtype != COERCION_PATH_RELABELTYPE)
404 : {
405 : /*
406 : * Generate an expression tree representing run-time application
407 : * of the conversion function. If we are dealing with a domain
408 : * target type, the conversion function will yield the base type,
409 : * and we need to extract the correct typmod to use from the
410 : * domain's typtypmod.
411 : */
412 : Oid baseTypeId;
413 : int32 baseTypeMod;
414 :
415 3906 : baseTypeMod = targetTypeMod;
416 3906 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
417 :
418 3906 : result = build_coercion_expression(node, pathtype, funcId,
419 : baseTypeId, baseTypeMod,
420 : cformat, location,
421 : (cformat != COERCE_IMPLICIT_CAST));
422 :
423 : /*
424 : * If domain, coerce to the domain type and relabel with domain
425 : * type ID. We can skip the internal length-coercion step if the
426 : * selected coercion function was a type-and-length coercion.
427 : */
428 3906 : if (targetTypeId != baseTypeId)
429 288 : result = coerce_to_domain(result, baseTypeId, baseTypeMod,
430 : targetTypeId,
431 : cformat, location, true,
432 288 : exprIsLengthCoercion(result,
433 : NULL));
434 : }
435 : else
436 : {
437 : /*
438 : * We don't need to do a physical conversion, but we do need to
439 : * attach a RelabelType node so that the expression will be seen
440 : * to have the intended type when inspected by higher-level code.
441 : *
442 : * Also, domains may have value restrictions beyond the base type
443 : * that must be accounted for. If the destination is a domain
444 : * then we won't need a RelabelType node.
445 : */
446 3924 : result = coerce_to_domain(node, InvalidOid, -1, targetTypeId,
447 : cformat, location, false, false);
448 3924 : if (result == node)
449 : {
450 : /*
451 : * XXX could we label result with exprTypmod(node) instead of
452 : * default -1 typmod, to save a possible length-coercion
453 : * later? Would work if both types have same interpretation of
454 : * typmod, which is likely but not certain.
455 : */
456 3621 : RelabelType *r = makeRelabelType((Expr *) result,
457 : targetTypeId, -1,
458 : InvalidOid,
459 : cformat);
460 :
461 3621 : r->location = location;
462 3621 : result = (Node *) r;
463 : }
464 : }
465 7830 : return result;
466 : }
467 303 : if (inputTypeId == RECORDOID &&
468 117 : ISCOMPLEX(targetTypeId))
469 : {
470 : /* Coerce a RECORD to a specific complex type */
471 117 : return coerce_record_to_complex(pstate, node, targetTypeId,
472 : ccontext, cformat, location);
473 : }
474 130 : if (targetTypeId == RECORDOID &&
475 61 : ISCOMPLEX(inputTypeId))
476 : {
477 : /* Coerce a specific complex type to RECORD */
478 : /* NB: we do NOT want a RelabelType here */
479 61 : return node;
480 : }
481 : #ifdef NOT_USED
482 : if (inputTypeId == RECORDARRAYOID &&
483 : is_complex_array(targetTypeId))
484 : {
485 : /* Coerce record[] to a specific complex array type */
486 : /* not implemented yet ... */
487 : }
488 : #endif
489 10 : if (targetTypeId == RECORDARRAYOID &&
490 2 : is_complex_array(inputTypeId))
491 : {
492 : /* Coerce a specific complex array type to record[] */
493 : /* NB: we do NOT want a RelabelType here */
494 2 : return node;
495 : }
496 6 : if (typeInheritsFrom(inputTypeId, targetTypeId)
497 1 : || typeIsOfTypedTable(inputTypeId, targetTypeId))
498 : {
499 : /*
500 : * Input class type is a subclass of target, so generate an
501 : * appropriate runtime conversion (removing unneeded columns and
502 : * possibly rearranging the ones that are wanted).
503 : */
504 6 : ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
505 :
506 6 : r->arg = (Expr *) node;
507 6 : r->resulttype = targetTypeId;
508 6 : r->convertformat = cformat;
509 6 : r->location = location;
510 6 : return (Node *) r;
511 : }
512 : /* If we get here, caller blew it */
513 0 : elog(ERROR, "failed to find conversion function from %s to %s",
514 : format_type_be(inputTypeId), format_type_be(targetTypeId));
515 : return NULL; /* keep compiler quiet */
516 : }
517 :
518 :
519 : /*
520 : * can_coerce_type()
521 : * Can input_typeids be coerced to target_typeids?
522 : *
523 : * We must be told the context (CAST construct, assignment, implicit coercion)
524 : * as this determines the set of available casts.
525 : */
526 : bool
527 64928 : can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
528 : CoercionContext ccontext)
529 : {
530 64928 : bool have_generics = false;
531 : int i;
532 :
533 : /* run through argument list... */
534 112625 : for (i = 0; i < nargs; i++)
535 : {
536 75044 : Oid inputTypeId = input_typeids[i];
537 75044 : Oid targetTypeId = target_typeids[i];
538 : CoercionPathType pathtype;
539 : Oid funcId;
540 :
541 : /* no problem if same type */
542 75044 : if (inputTypeId == targetTypeId)
543 58030 : continue;
544 :
545 : /* accept if target is ANY */
546 64711 : if (targetTypeId == ANYOID)
547 674 : continue;
548 :
549 : /* accept if target is polymorphic, for now */
550 64037 : if (IsPolymorphicType(targetTypeId))
551 : {
552 7347 : have_generics = true; /* do more checking later */
553 7347 : continue;
554 : }
555 :
556 : /*
557 : * If input is an untyped string constant, assume we can convert it to
558 : * anything.
559 : */
560 56690 : if (inputTypeId == UNKNOWNOID)
561 21720 : continue;
562 :
563 : /*
564 : * If pg_cast shows that we can coerce, accept. This test now covers
565 : * both binary-compatible and coercion-function cases.
566 : */
567 34970 : pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
568 : &funcId);
569 34970 : if (pathtype != COERCION_PATH_NONE)
570 7445 : continue;
571 :
572 : /*
573 : * If input is RECORD and target is a composite type, assume we can
574 : * coerce (may need tighter checking here)
575 : */
576 27656 : if (inputTypeId == RECORDOID &&
577 131 : ISCOMPLEX(targetTypeId))
578 117 : continue;
579 :
580 : /*
581 : * If input is a composite type and target is RECORD, accept
582 : */
583 27802 : if (targetTypeId == RECORDOID &&
584 394 : ISCOMPLEX(inputTypeId))
585 55 : continue;
586 :
587 : #ifdef NOT_USED /* not implemented yet */
588 :
589 : /*
590 : * If input is record[] and target is a composite array type, assume
591 : * we can coerce (may need tighter checking here)
592 : */
593 : if (inputTypeId == RECORDARRAYOID &&
594 : is_complex_array(targetTypeId))
595 : continue;
596 : #endif
597 :
598 : /*
599 : * If input is a composite array type and target is record[], accept
600 : */
601 27353 : if (targetTypeId == RECORDARRAYOID &&
602 0 : is_complex_array(inputTypeId))
603 0 : continue;
604 :
605 : /*
606 : * If input is a class type that inherits from target, accept
607 : */
608 27353 : if (typeInheritsFrom(inputTypeId, targetTypeId)
609 27348 : || typeIsOfTypedTable(inputTypeId, targetTypeId))
610 6 : continue;
611 :
612 : /*
613 : * Else, cannot coerce at this argument position
614 : */
615 27347 : return false;
616 : }
617 :
618 : /* If we found any generic argument types, cross-check them */
619 37581 : if (have_generics)
620 : {
621 5506 : if (!check_generic_type_consistency(input_typeids, target_typeids,
622 : nargs))
623 2479 : return false;
624 : }
625 :
626 35102 : return true;
627 : }
628 :
629 :
630 : /*
631 : * Create an expression tree to represent coercion to a domain type.
632 : *
633 : * 'arg': input expression
634 : * 'baseTypeId': base type of domain, if known (pass InvalidOid if caller
635 : * has not bothered to look this up)
636 : * 'baseTypeMod': base type typmod of domain, if known (pass -1 if caller
637 : * has not bothered to look this up)
638 : * 'typeId': target type to coerce to
639 : * 'cformat': coercion format
640 : * 'location': coercion request location
641 : * 'hideInputCoercion': if true, hide the input coercion under this one.
642 : * 'lengthCoercionDone': if true, caller already accounted for length,
643 : * ie the input is already of baseTypMod as well as baseTypeId.
644 : *
645 : * If the target type isn't a domain, the given 'arg' is returned as-is.
646 : */
647 : Node *
648 5286 : coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
649 : CoercionForm cformat, int location,
650 : bool hideInputCoercion,
651 : bool lengthCoercionDone)
652 : {
653 : CoerceToDomain *result;
654 :
655 : /* Get the base type if it hasn't been supplied */
656 5286 : if (baseTypeId == InvalidOid)
657 4471 : baseTypeId = getBaseTypeAndTypmod(typeId, &baseTypeMod);
658 :
659 : /* If it isn't a domain, return the node as it was passed in */
660 5286 : if (baseTypeId == typeId)
661 4159 : return arg;
662 :
663 : /* Suppress display of nested coercion steps */
664 1127 : if (hideInputCoercion)
665 288 : hide_coercion_node(arg);
666 :
667 : /*
668 : * If the domain applies a typmod to its base type, build the appropriate
669 : * coercion step. Mark it implicit for display purposes, because we don't
670 : * want it shown separately by ruleutils.c; but the isExplicit flag passed
671 : * to the conversion function depends on the manner in which the domain
672 : * coercion is invoked, so that the semantics of implicit and explicit
673 : * coercion differ. (Is that really the behavior we want?)
674 : *
675 : * NOTE: because we apply this as part of the fixed expression structure,
676 : * ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
677 : * would be safe to do anyway, without lots of knowledge about what the
678 : * base type thinks the typmod means.
679 : */
680 1127 : if (!lengthCoercionDone)
681 : {
682 1127 : if (baseTypeMod >= 0)
683 147 : arg = coerce_type_typmod(arg, baseTypeId, baseTypeMod,
684 : COERCE_IMPLICIT_CAST, location,
685 : (cformat != COERCE_IMPLICIT_CAST),
686 : false);
687 : }
688 :
689 : /*
690 : * Now build the domain coercion node. This represents run-time checking
691 : * of any constraints currently attached to the domain. This also ensures
692 : * that the expression is properly labeled as to result type.
693 : */
694 1127 : result = makeNode(CoerceToDomain);
695 1127 : result->arg = (Expr *) arg;
696 1127 : result->resulttype = typeId;
697 1127 : result->resulttypmod = -1; /* currently, always -1 for domains */
698 : /* resultcollid will be set by parse_collate.c */
699 1127 : result->coercionformat = cformat;
700 1127 : result->location = location;
701 :
702 1127 : return (Node *) result;
703 : }
704 :
705 :
706 : /*
707 : * coerce_type_typmod()
708 : * Force a value to a particular typmod, if meaningful and possible.
709 : *
710 : * This is applied to values that are going to be stored in a relation
711 : * (where we have an atttypmod for the column) as well as values being
712 : * explicitly CASTed (where the typmod comes from the target type spec).
713 : *
714 : * The caller must have already ensured that the value is of the correct
715 : * type, typically by applying coerce_type.
716 : *
717 : * cformat determines the display properties of the generated node (if any),
718 : * while isExplicit may affect semantics. If hideInputCoercion is true
719 : * *and* we generate a node, the input node is forced to IMPLICIT display
720 : * form, so that only the typmod coercion node will be visible when
721 : * displaying the expression.
722 : *
723 : * NOTE: this does not need to work on domain types, because any typmod
724 : * coercion for a domain is considered to be part of the type coercion
725 : * needed to produce the domain value in the first place. So, no getBaseType.
726 : */
727 : static Node *
728 21926 : coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
729 : CoercionForm cformat, int location,
730 : bool isExplicit, bool hideInputCoercion)
731 : {
732 : CoercionPathType pathtype;
733 : Oid funcId;
734 :
735 : /*
736 : * A negative typmod is assumed to mean that no coercion is wanted. Also,
737 : * skip coercion if already done.
738 : */
739 21926 : if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
740 20251 : return node;
741 :
742 1675 : pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
743 :
744 1675 : if (pathtype != COERCION_PATH_NONE)
745 : {
746 : /* Suppress display of nested coercion steps */
747 1675 : if (hideInputCoercion)
748 37 : hide_coercion_node(node);
749 :
750 1675 : node = build_coercion_expression(node, pathtype, funcId,
751 : targetTypeId, targetTypMod,
752 : cformat, location,
753 : isExplicit);
754 : }
755 :
756 1675 : return node;
757 : }
758 :
759 : /*
760 : * Mark a coercion node as IMPLICIT so it will never be displayed by
761 : * ruleutils.c. We use this when we generate a nest of coercion nodes
762 : * to implement what is logically one conversion; the inner nodes are
763 : * forced to IMPLICIT_CAST format. This does not change their semantics,
764 : * only display behavior.
765 : *
766 : * It is caller error to call this on something that doesn't have a
767 : * CoercionForm field.
768 : */
769 : static void
770 325 : hide_coercion_node(Node *node)
771 : {
772 325 : if (IsA(node, FuncExpr))
773 280 : ((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
774 45 : else if (IsA(node, RelabelType))
775 23 : ((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
776 22 : else if (IsA(node, CoerceViaIO))
777 22 : ((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
778 0 : else if (IsA(node, ArrayCoerceExpr))
779 0 : ((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
780 0 : else if (IsA(node, ConvertRowtypeExpr))
781 0 : ((ConvertRowtypeExpr *) node)->convertformat = COERCE_IMPLICIT_CAST;
782 0 : else if (IsA(node, RowExpr))
783 0 : ((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
784 0 : else if (IsA(node, CoerceToDomain))
785 0 : ((CoerceToDomain *) node)->coercionformat = COERCE_IMPLICIT_CAST;
786 : else
787 0 : elog(ERROR, "unsupported node type: %d", (int) nodeTag(node));
788 325 : }
789 :
790 : /*
791 : * build_coercion_expression()
792 : * Construct an expression tree for applying a pg_cast entry.
793 : *
794 : * This is used for both type-coercion and length-coercion operations,
795 : * since there is no difference in terms of the calling convention.
796 : */
797 : static Node *
798 5581 : build_coercion_expression(Node *node,
799 : CoercionPathType pathtype,
800 : Oid funcId,
801 : Oid targetTypeId, int32 targetTypMod,
802 : CoercionForm cformat, int location,
803 : bool isExplicit)
804 : {
805 5581 : int nargs = 0;
806 :
807 5581 : if (OidIsValid(funcId))
808 : {
809 : HeapTuple tp;
810 : Form_pg_proc procstruct;
811 :
812 4804 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
813 4804 : if (!HeapTupleIsValid(tp))
814 0 : elog(ERROR, "cache lookup failed for function %u", funcId);
815 4804 : procstruct = (Form_pg_proc) GETSTRUCT(tp);
816 :
817 : /*
818 : * These Asserts essentially check that function is a legal coercion
819 : * function. We can't make the seemingly obvious tests on prorettype
820 : * and proargtypes[0], even in the COERCION_PATH_FUNC case, because of
821 : * various binary-compatibility cases.
822 : */
823 : /* Assert(targetTypeId == procstruct->prorettype); */
824 4804 : Assert(!procstruct->proretset);
825 4804 : Assert(!procstruct->proisagg);
826 4804 : Assert(!procstruct->proiswindow);
827 4804 : nargs = procstruct->pronargs;
828 4804 : Assert(nargs >= 1 && nargs <= 3);
829 : /* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
830 4804 : Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
831 4804 : Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
832 :
833 4804 : ReleaseSysCache(tp);
834 : }
835 :
836 5581 : if (pathtype == COERCION_PATH_FUNC)
837 : {
838 : /* We build an ordinary FuncExpr with special arguments */
839 : FuncExpr *fexpr;
840 : List *args;
841 : Const *cons;
842 :
843 4776 : Assert(OidIsValid(funcId));
844 :
845 4776 : args = list_make1(node);
846 :
847 4776 : if (nargs >= 2)
848 : {
849 : /* Pass target typmod as an int4 constant */
850 1847 : cons = makeConst(INT4OID,
851 : -1,
852 : InvalidOid,
853 : sizeof(int32),
854 : Int32GetDatum(targetTypMod),
855 : false,
856 : true);
857 :
858 1847 : args = lappend(args, cons);
859 : }
860 :
861 4776 : if (nargs == 3)
862 : {
863 : /* Pass it a boolean isExplicit parameter, too */
864 992 : cons = makeConst(BOOLOID,
865 : -1,
866 : InvalidOid,
867 : sizeof(bool),
868 : BoolGetDatum(isExplicit),
869 : false,
870 : true);
871 :
872 992 : args = lappend(args, cons);
873 : }
874 :
875 4776 : fexpr = makeFuncExpr(funcId, targetTypeId, args,
876 : InvalidOid, InvalidOid, cformat);
877 4776 : fexpr->location = location;
878 4776 : return (Node *) fexpr;
879 : }
880 805 : else if (pathtype == COERCION_PATH_ARRAYCOERCE)
881 : {
882 : /* We need to build an ArrayCoerceExpr */
883 54 : ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
884 :
885 54 : acoerce->arg = (Expr *) node;
886 54 : acoerce->elemfuncid = funcId;
887 54 : acoerce->resulttype = targetTypeId;
888 :
889 : /*
890 : * Label the output as having a particular typmod only if we are
891 : * really invoking a length-coercion function, ie one with more than
892 : * one argument.
893 : */
894 54 : acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
895 : /* resultcollid will be set by parse_collate.c */
896 54 : acoerce->isExplicit = isExplicit;
897 54 : acoerce->coerceformat = cformat;
898 54 : acoerce->location = location;
899 :
900 54 : return (Node *) acoerce;
901 : }
902 751 : else if (pathtype == COERCION_PATH_COERCEVIAIO)
903 : {
904 : /* We need to build a CoerceViaIO node */
905 751 : CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
906 :
907 751 : Assert(!OidIsValid(funcId));
908 :
909 751 : iocoerce->arg = (Expr *) node;
910 751 : iocoerce->resulttype = targetTypeId;
911 : /* resultcollid will be set by parse_collate.c */
912 751 : iocoerce->coerceformat = cformat;
913 751 : iocoerce->location = location;
914 :
915 751 : return (Node *) iocoerce;
916 : }
917 : else
918 : {
919 0 : elog(ERROR, "unsupported pathtype %d in build_coercion_expression",
920 : (int) pathtype);
921 : return NULL; /* keep compiler quiet */
922 : }
923 : }
924 :
925 :
926 : /*
927 : * coerce_record_to_complex
928 : * Coerce a RECORD to a specific composite type.
929 : *
930 : * Currently we only support this for inputs that are RowExprs or whole-row
931 : * Vars.
932 : */
933 : static Node *
934 117 : coerce_record_to_complex(ParseState *pstate, Node *node,
935 : Oid targetTypeId,
936 : CoercionContext ccontext,
937 : CoercionForm cformat,
938 : int location)
939 : {
940 : RowExpr *rowexpr;
941 : TupleDesc tupdesc;
942 117 : List *args = NIL;
943 : List *newargs;
944 : int i;
945 : int ucolno;
946 : ListCell *arg;
947 :
948 117 : if (node && IsA(node, RowExpr))
949 : {
950 : /*
951 : * Since the RowExpr must be of type RECORD, we needn't worry about it
952 : * containing any dropped columns.
953 : */
954 117 : args = ((RowExpr *) node)->args;
955 : }
956 0 : else if (node && IsA(node, Var) &&
957 0 : ((Var *) node)->varattno == InvalidAttrNumber)
958 0 : {
959 0 : int rtindex = ((Var *) node)->varno;
960 0 : int sublevels_up = ((Var *) node)->varlevelsup;
961 0 : int vlocation = ((Var *) node)->location;
962 : RangeTblEntry *rte;
963 :
964 0 : rte = GetRTEByRangeTablePosn(pstate, rtindex, sublevels_up);
965 0 : expandRTE(rte, rtindex, sublevels_up, vlocation, false,
966 : NULL, &args);
967 : }
968 : else
969 0 : ereport(ERROR,
970 : (errcode(ERRCODE_CANNOT_COERCE),
971 : errmsg("cannot cast type %s to %s",
972 : format_type_be(RECORDOID),
973 : format_type_be(targetTypeId)),
974 : parser_coercion_errposition(pstate, location, node)));
975 :
976 117 : tupdesc = lookup_rowtype_tupdesc(targetTypeId, -1);
977 117 : newargs = NIL;
978 117 : ucolno = 1;
979 117 : arg = list_head(args);
980 423 : for (i = 0; i < tupdesc->natts; i++)
981 : {
982 : Node *expr;
983 : Node *cexpr;
984 : Oid exprtype;
985 306 : Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
986 :
987 : /* Fill in NULLs for dropped columns in rowtype */
988 306 : if (attr->attisdropped)
989 : {
990 : /*
991 : * can't use atttypid here, but it doesn't really matter what type
992 : * the Const claims to be.
993 : */
994 0 : newargs = lappend(newargs,
995 0 : makeNullConst(INT4OID, -1, InvalidOid));
996 0 : continue;
997 : }
998 :
999 306 : if (arg == NULL)
1000 0 : ereport(ERROR,
1001 : (errcode(ERRCODE_CANNOT_COERCE),
1002 : errmsg("cannot cast type %s to %s",
1003 : format_type_be(RECORDOID),
1004 : format_type_be(targetTypeId)),
1005 : errdetail("Input has too few columns."),
1006 : parser_coercion_errposition(pstate, location, node)));
1007 306 : expr = (Node *) lfirst(arg);
1008 306 : exprtype = exprType(expr);
1009 :
1010 306 : cexpr = coerce_to_target_type(pstate,
1011 : expr, exprtype,
1012 : attr->atttypid,
1013 : attr->atttypmod,
1014 : ccontext,
1015 : COERCE_IMPLICIT_CAST,
1016 : -1);
1017 306 : if (cexpr == NULL)
1018 0 : ereport(ERROR,
1019 : (errcode(ERRCODE_CANNOT_COERCE),
1020 : errmsg("cannot cast type %s to %s",
1021 : format_type_be(RECORDOID),
1022 : format_type_be(targetTypeId)),
1023 : errdetail("Cannot cast type %s to %s in column %d.",
1024 : format_type_be(exprtype),
1025 : format_type_be(attr->atttypid),
1026 : ucolno),
1027 : parser_coercion_errposition(pstate, location, expr)));
1028 306 : newargs = lappend(newargs, cexpr);
1029 306 : ucolno++;
1030 306 : arg = lnext(arg);
1031 : }
1032 117 : if (arg != NULL)
1033 0 : ereport(ERROR,
1034 : (errcode(ERRCODE_CANNOT_COERCE),
1035 : errmsg("cannot cast type %s to %s",
1036 : format_type_be(RECORDOID),
1037 : format_type_be(targetTypeId)),
1038 : errdetail("Input has too many columns."),
1039 : parser_coercion_errposition(pstate, location, node)));
1040 :
1041 117 : ReleaseTupleDesc(tupdesc);
1042 :
1043 117 : rowexpr = makeNode(RowExpr);
1044 117 : rowexpr->args = newargs;
1045 117 : rowexpr->row_typeid = targetTypeId;
1046 117 : rowexpr->row_format = cformat;
1047 117 : rowexpr->colnames = NIL; /* not needed for named target type */
1048 117 : rowexpr->location = location;
1049 117 : return (Node *) rowexpr;
1050 : }
1051 :
1052 : /*
1053 : * coerce_to_boolean()
1054 : * Coerce an argument of a construct that requires boolean input
1055 : * (AND, OR, NOT, etc). Also check that input is not a set.
1056 : *
1057 : * Returns the possibly-transformed node tree.
1058 : *
1059 : * As with coerce_type, pstate may be NULL if no special unknown-Param
1060 : * processing is wanted.
1061 : */
1062 : Node *
1063 23687 : coerce_to_boolean(ParseState *pstate, Node *node,
1064 : const char *constructName)
1065 : {
1066 23687 : Oid inputTypeId = exprType(node);
1067 :
1068 23687 : if (inputTypeId != BOOLOID)
1069 : {
1070 : Node *newnode;
1071 :
1072 0 : newnode = coerce_to_target_type(pstate, node, inputTypeId,
1073 : BOOLOID, -1,
1074 : COERCION_ASSIGNMENT,
1075 : COERCE_IMPLICIT_CAST,
1076 : -1);
1077 0 : if (newnode == NULL)
1078 0 : ereport(ERROR,
1079 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1080 : /* translator: first %s is name of a SQL construct, eg WHERE */
1081 : errmsg("argument of %s must be type %s, not type %s",
1082 : constructName, "boolean",
1083 : format_type_be(inputTypeId)),
1084 : parser_errposition(pstate, exprLocation(node))));
1085 0 : node = newnode;
1086 : }
1087 :
1088 23687 : if (expression_returns_set(node))
1089 0 : ereport(ERROR,
1090 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1091 : /* translator: %s is name of a SQL construct, eg WHERE */
1092 : errmsg("argument of %s must not return a set",
1093 : constructName),
1094 : parser_errposition(pstate, exprLocation(node))));
1095 :
1096 23687 : return node;
1097 : }
1098 :
1099 : /*
1100 : * coerce_to_specific_type_typmod()
1101 : * Coerce an argument of a construct that requires a specific data type,
1102 : * with a specific typmod. Also check that input is not a set.
1103 : *
1104 : * Returns the possibly-transformed node tree.
1105 : *
1106 : * As with coerce_type, pstate may be NULL if no special unknown-Param
1107 : * processing is wanted.
1108 : */
1109 : Node *
1110 534 : coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
1111 : Oid targetTypeId, int32 targetTypmod,
1112 : const char *constructName)
1113 : {
1114 534 : Oid inputTypeId = exprType(node);
1115 :
1116 534 : if (inputTypeId != targetTypeId)
1117 : {
1118 : Node *newnode;
1119 :
1120 464 : newnode = coerce_to_target_type(pstate, node, inputTypeId,
1121 : targetTypeId, targetTypmod,
1122 : COERCION_ASSIGNMENT,
1123 : COERCE_IMPLICIT_CAST,
1124 : -1);
1125 442 : if (newnode == NULL)
1126 1 : ereport(ERROR,
1127 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1128 : /* translator: first %s is name of a SQL construct, eg LIMIT */
1129 : errmsg("argument of %s must be type %s, not type %s",
1130 : constructName,
1131 : format_type_be(targetTypeId),
1132 : format_type_be(inputTypeId)),
1133 : parser_errposition(pstate, exprLocation(node))));
1134 441 : node = newnode;
1135 : }
1136 :
1137 511 : if (expression_returns_set(node))
1138 0 : ereport(ERROR,
1139 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1140 : /* translator: %s is name of a SQL construct, eg LIMIT */
1141 : errmsg("argument of %s must not return a set",
1142 : constructName),
1143 : parser_errposition(pstate, exprLocation(node))));
1144 :
1145 511 : return node;
1146 : }
1147 :
1148 : /*
1149 : * coerce_to_specific_type()
1150 : * Coerce an argument of a construct that requires a specific data type.
1151 : * Also check that input is not a set.
1152 : *
1153 : * Returns the possibly-transformed node tree.
1154 : *
1155 : * As with coerce_type, pstate may be NULL if no special unknown-Param
1156 : * processing is wanted.
1157 : */
1158 : Node *
1159 525 : coerce_to_specific_type(ParseState *pstate, Node *node,
1160 : Oid targetTypeId,
1161 : const char *constructName)
1162 : {
1163 525 : return coerce_to_specific_type_typmod(pstate, node,
1164 : targetTypeId, -1,
1165 : constructName);
1166 : }
1167 :
1168 : /*
1169 : * parser_coercion_errposition - report coercion error location, if possible
1170 : *
1171 : * We prefer to point at the coercion request (CAST, ::, etc) if possible;
1172 : * but there may be no such location in the case of an implicit coercion.
1173 : * In that case point at the input expression.
1174 : *
1175 : * XXX possibly this is more generally useful than coercion errors;
1176 : * if so, should rename and place with parser_errposition.
1177 : */
1178 : int
1179 3 : parser_coercion_errposition(ParseState *pstate,
1180 : int coerce_location,
1181 : Node *input_expr)
1182 : {
1183 3 : if (coerce_location >= 0)
1184 3 : return parser_errposition(pstate, coerce_location);
1185 : else
1186 0 : return parser_errposition(pstate, exprLocation(input_expr));
1187 : }
1188 :
1189 :
1190 : /*
1191 : * select_common_type()
1192 : * Determine the common supertype of a list of input expressions.
1193 : * This is used for determining the output type of CASE, UNION,
1194 : * and similar constructs.
1195 : *
1196 : * 'exprs' is a *nonempty* list of expressions. Note that earlier items
1197 : * in the list will be preferred if there is doubt.
1198 : * 'context' is a phrase to use in the error message if we fail to select
1199 : * a usable type. Pass NULL to have the routine return InvalidOid
1200 : * rather than throwing an error on failure.
1201 : * 'which_expr': if not NULL, receives a pointer to the particular input
1202 : * expression from which the result type was taken.
1203 : */
1204 : Oid
1205 3402 : select_common_type(ParseState *pstate, List *exprs, const char *context,
1206 : Node **which_expr)
1207 : {
1208 : Node *pexpr;
1209 : Oid ptype;
1210 : TYPCATEGORY pcategory;
1211 : bool pispreferred;
1212 : ListCell *lc;
1213 :
1214 3402 : Assert(exprs != NIL);
1215 3402 : pexpr = (Node *) linitial(exprs);
1216 3402 : lc = lnext(list_head(exprs));
1217 3402 : ptype = exprType(pexpr);
1218 :
1219 : /*
1220 : * If all input types are valid and exactly the same, just pick that type.
1221 : * This is the only way that we will resolve the result as being a domain
1222 : * type; otherwise domains are smashed to their base types for comparison.
1223 : */
1224 3402 : if (ptype != UNKNOWNOID)
1225 : {
1226 5100 : for_each_cell(lc, lc)
1227 : {
1228 3448 : Node *nexpr = (Node *) lfirst(lc);
1229 3448 : Oid ntype = exprType(nexpr);
1230 :
1231 3448 : if (ntype != ptype)
1232 1130 : break;
1233 : }
1234 2782 : if (lc == NULL) /* got to the end of the list? */
1235 : {
1236 1652 : if (which_expr)
1237 766 : *which_expr = pexpr;
1238 1652 : return ptype;
1239 : }
1240 : }
1241 :
1242 : /*
1243 : * Nope, so set up for the full algorithm. Note that at this point, lc
1244 : * points to the first list item with type different from pexpr's; we need
1245 : * not re-examine any items the previous loop advanced over.
1246 : */
1247 1750 : ptype = getBaseType(ptype);
1248 1750 : get_type_category_preferred(ptype, &pcategory, &pispreferred);
1249 :
1250 5416 : for_each_cell(lc, lc)
1251 : {
1252 3667 : Node *nexpr = (Node *) lfirst(lc);
1253 3667 : Oid ntype = getBaseType(exprType(nexpr));
1254 :
1255 : /* move on to next one if no new information... */
1256 3667 : if (ntype != UNKNOWNOID && ntype != ptype)
1257 : {
1258 : TYPCATEGORY ncategory;
1259 : bool nispreferred;
1260 :
1261 353 : get_type_category_preferred(ntype, &ncategory, &nispreferred);
1262 353 : if (ptype == UNKNOWNOID)
1263 : {
1264 : /* so far, only unknowns so take anything... */
1265 109 : pexpr = nexpr;
1266 109 : ptype = ntype;
1267 109 : pcategory = ncategory;
1268 109 : pispreferred = nispreferred;
1269 : }
1270 244 : else if (ncategory != pcategory)
1271 : {
1272 : /*
1273 : * both types in different categories? then not much hope...
1274 : */
1275 1 : if (context == NULL)
1276 0 : return InvalidOid;
1277 1 : ereport(ERROR,
1278 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1279 : /*------
1280 : translator: first %s is name of a SQL construct, eg CASE */
1281 : errmsg("%s types %s and %s cannot be matched",
1282 : context,
1283 : format_type_be(ptype),
1284 : format_type_be(ntype)),
1285 : parser_errposition(pstate, exprLocation(nexpr))));
1286 : }
1287 341 : else if (!pispreferred &&
1288 126 : can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
1289 28 : !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
1290 : {
1291 : /*
1292 : * take new type if can coerce to it implicitly but not the
1293 : * other way; but if we have a preferred type, stay on it.
1294 : */
1295 25 : pexpr = nexpr;
1296 25 : ptype = ntype;
1297 25 : pcategory = ncategory;
1298 25 : pispreferred = nispreferred;
1299 : }
1300 : }
1301 : }
1302 :
1303 : /*
1304 : * If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
1305 : * then resolve as type TEXT. This situation comes up with constructs
1306 : * like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
1307 : * UNION SELECT 'bar'; It might seem desirable to leave the construct's
1308 : * output type as UNKNOWN, but that really doesn't work, because we'd
1309 : * probably end up needing a runtime coercion from UNKNOWN to something
1310 : * else, and we usually won't have it. We need to coerce the unknown
1311 : * literals while they are still literals, so a decision has to be made
1312 : * now.
1313 : */
1314 1749 : if (ptype == UNKNOWNOID)
1315 511 : ptype = TEXTOID;
1316 :
1317 1749 : if (which_expr)
1318 59 : *which_expr = pexpr;
1319 1749 : return ptype;
1320 : }
1321 :
1322 : /*
1323 : * coerce_to_common_type()
1324 : * Coerce an expression to the given type.
1325 : *
1326 : * This is used following select_common_type() to coerce the individual
1327 : * expressions to the desired type. 'context' is a phrase to use in the
1328 : * error message if we fail to coerce.
1329 : *
1330 : * As with coerce_type, pstate may be NULL if no special unknown-Param
1331 : * processing is wanted.
1332 : */
1333 : Node *
1334 9068 : coerce_to_common_type(ParseState *pstate, Node *node,
1335 : Oid targetTypeId, const char *context)
1336 : {
1337 9068 : Oid inputTypeId = exprType(node);
1338 :
1339 9068 : if (inputTypeId == targetTypeId)
1340 5096 : return node; /* no work */
1341 3972 : if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
1342 3972 : node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
1343 : COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
1344 : else
1345 0 : ereport(ERROR,
1346 : (errcode(ERRCODE_CANNOT_COERCE),
1347 : /* translator: first %s is name of a SQL construct, eg CASE */
1348 : errmsg("%s could not convert type %s to %s",
1349 : context,
1350 : format_type_be(inputTypeId),
1351 : format_type_be(targetTypeId)),
1352 : parser_errposition(pstate, exprLocation(node))));
1353 3971 : return node;
1354 : }
1355 :
1356 : /*
1357 : * check_generic_type_consistency()
1358 : * Are the actual arguments potentially compatible with a
1359 : * polymorphic function?
1360 : *
1361 : * The argument consistency rules are:
1362 : *
1363 : * 1) All arguments declared ANYELEMENT must have the same datatype.
1364 : * 2) All arguments declared ANYARRAY must have the same datatype,
1365 : * which must be a varlena array type.
1366 : * 3) All arguments declared ANYRANGE must have the same datatype,
1367 : * which must be a range type.
1368 : * 4) If there are arguments of both ANYELEMENT and ANYARRAY, make sure the
1369 : * actual ANYELEMENT datatype is in fact the element type for the actual
1370 : * ANYARRAY datatype.
1371 : * 5) Similarly, if there are arguments of both ANYELEMENT and ANYRANGE,
1372 : * make sure the actual ANYELEMENT datatype is in fact the subtype for
1373 : * the actual ANYRANGE type.
1374 : * 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
1375 : * (alone or in combination with plain ANYELEMENT), we add the extra
1376 : * condition that the ANYELEMENT type must be an enum.
1377 : * 7) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
1378 : * we add the extra condition that the ANYELEMENT type must not be an array.
1379 : * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
1380 : * is an extra restriction if not.)
1381 : *
1382 : * Domains over arrays match ANYARRAY, and are immediately flattened to their
1383 : * base type. (Thus, for example, we will consider it a match if one ANYARRAY
1384 : * argument is a domain over int4[] while another one is just int4[].) Also
1385 : * notice that such a domain does *not* match ANYNONARRAY.
1386 : *
1387 : * Similarly, domains over ranges match ANYRANGE, and are immediately
1388 : * flattened to their base type.
1389 : *
1390 : * Note that domains aren't currently considered to match ANYENUM,
1391 : * even if their base type would match.
1392 : *
1393 : * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
1394 : * argument, assume it is okay.
1395 : *
1396 : * If an input is of type ANYARRAY (ie, we know it's an array, but not
1397 : * what element type), we will accept it as a match to an argument declared
1398 : * ANYARRAY, so long as we don't have to determine an element type ---
1399 : * that is, so long as there is no use of ANYELEMENT. This is mostly for
1400 : * backwards compatibility with the pre-7.4 behavior of ANYARRAY.
1401 : *
1402 : * We do not ereport here, but just return FALSE if a rule is violated.
1403 : */
1404 : bool
1405 5506 : check_generic_type_consistency(Oid *actual_arg_types,
1406 : Oid *declared_arg_types,
1407 : int nargs)
1408 : {
1409 : int j;
1410 5506 : Oid elem_typeid = InvalidOid;
1411 5506 : Oid array_typeid = InvalidOid;
1412 : Oid array_typelem;
1413 5506 : Oid range_typeid = InvalidOid;
1414 : Oid range_typelem;
1415 5506 : bool have_anyelement = false;
1416 5506 : bool have_anynonarray = false;
1417 5506 : bool have_anyenum = false;
1418 :
1419 : /*
1420 : * Loop through the arguments to see if we have any that are polymorphic.
1421 : * If so, require the actual types to be consistent.
1422 : */
1423 12928 : for (j = 0; j < nargs; j++)
1424 : {
1425 8233 : Oid decl_type = declared_arg_types[j];
1426 8233 : Oid actual_type = actual_arg_types[j];
1427 :
1428 8233 : if (decl_type == ANYELEMENTOID ||
1429 6343 : decl_type == ANYNONARRAYOID ||
1430 : decl_type == ANYENUMOID)
1431 : {
1432 2671 : have_anyelement = true;
1433 2671 : if (decl_type == ANYNONARRAYOID)
1434 1107 : have_anynonarray = true;
1435 1564 : else if (decl_type == ANYENUMOID)
1436 781 : have_anyenum = true;
1437 2671 : if (actual_type == UNKNOWNOID)
1438 207 : continue;
1439 2464 : if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
1440 241 : return false;
1441 2223 : elem_typeid = actual_type;
1442 : }
1443 5562 : else if (decl_type == ANYARRAYOID)
1444 : {
1445 3451 : if (actual_type == UNKNOWNOID)
1446 185 : continue;
1447 3266 : actual_type = getBaseType(actual_type); /* flatten domains */
1448 3266 : if (OidIsValid(array_typeid) && actual_type != array_typeid)
1449 270 : return false;
1450 2996 : array_typeid = actual_type;
1451 : }
1452 2111 : else if (decl_type == ANYRANGEOID)
1453 : {
1454 1175 : if (actual_type == UNKNOWNOID)
1455 120 : continue;
1456 1055 : actual_type = getBaseType(actual_type); /* flatten domains */
1457 1055 : if (OidIsValid(range_typeid) && actual_type != range_typeid)
1458 300 : return false;
1459 755 : range_typeid = actual_type;
1460 : }
1461 : }
1462 :
1463 : /* Get the element type based on the array type, if we have one */
1464 4695 : if (OidIsValid(array_typeid))
1465 : {
1466 2610 : if (array_typeid == ANYARRAYOID)
1467 : {
1468 : /* Special case for ANYARRAY input: okay iff no ANYELEMENT */
1469 0 : if (have_anyelement)
1470 0 : return false;
1471 0 : return true;
1472 : }
1473 :
1474 2610 : array_typelem = get_element_type(array_typeid);
1475 2610 : if (!OidIsValid(array_typelem))
1476 1218 : return false; /* should be an array, but isn't */
1477 :
1478 1392 : if (!OidIsValid(elem_typeid))
1479 : {
1480 : /*
1481 : * if we don't have an element type yet, use the one we just got
1482 : */
1483 1269 : elem_typeid = array_typelem;
1484 : }
1485 123 : else if (array_typelem != elem_typeid)
1486 : {
1487 : /* otherwise, they better match */
1488 56 : return false;
1489 : }
1490 : }
1491 :
1492 : /* Get the element type based on the range type, if we have one */
1493 3421 : if (OidIsValid(range_typeid))
1494 : {
1495 341 : range_typelem = get_range_subtype(range_typeid);
1496 341 : if (!OidIsValid(range_typelem))
1497 236 : return false; /* should be a range, but isn't */
1498 :
1499 105 : if (!OidIsValid(elem_typeid))
1500 : {
1501 : /*
1502 : * if we don't have an element type yet, use the one we just got
1503 : */
1504 82 : elem_typeid = range_typelem;
1505 : }
1506 23 : else if (range_typelem != elem_typeid)
1507 : {
1508 : /* otherwise, they better match */
1509 10 : return false;
1510 : }
1511 : }
1512 :
1513 3175 : if (have_anynonarray)
1514 : {
1515 : /* require the element type to not be an array or domain over array */
1516 1107 : if (type_is_array_domain(elem_typeid))
1517 10 : return false;
1518 : }
1519 :
1520 3165 : if (have_anyenum)
1521 : {
1522 : /* require the element type to be an enum */
1523 183 : if (!type_is_enum(elem_typeid))
1524 138 : return false;
1525 : }
1526 :
1527 : /* Looks valid */
1528 3027 : return true;
1529 : }
1530 :
1531 : /*
1532 : * enforce_generic_type_consistency()
1533 : * Make sure a polymorphic function is legally callable, and
1534 : * deduce actual argument and result types.
1535 : *
1536 : * If any polymorphic pseudotype is used in a function's arguments or
1537 : * return type, we make sure the actual data types are consistent with
1538 : * each other. The argument consistency rules are shown above for
1539 : * check_generic_type_consistency().
1540 : *
1541 : * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
1542 : * argument, we attempt to deduce the actual type it should have. If
1543 : * successful, we alter that position of declared_arg_types[] so that
1544 : * make_fn_arguments will coerce the literal to the right thing.
1545 : *
1546 : * Rules are applied to the function's return type (possibly altering it)
1547 : * if it is declared as a polymorphic type:
1548 : *
1549 : * 1) If return type is ANYARRAY, and any argument is ANYARRAY, use the
1550 : * argument's actual type as the function's return type.
1551 : * 2) Similarly, if return type is ANYRANGE, and any argument is ANYRANGE,
1552 : * use the argument's actual type as the function's return type.
1553 : * 3) If return type is ANYARRAY, no argument is ANYARRAY, but any argument is
1554 : * ANYELEMENT, use the actual type of the argument to determine the
1555 : * function's return type, i.e. the element type's corresponding array
1556 : * type. (Note: similar behavior does not exist for ANYRANGE, because it's
1557 : * impossible to determine the range type from the subtype alone.)
1558 : * 4) If return type is ANYARRAY, but no argument is ANYARRAY or ANYELEMENT,
1559 : * generate an error. Similarly, if return type is ANYRANGE, but no
1560 : * argument is ANYRANGE, generate an error. (These conditions are
1561 : * prevented by CREATE FUNCTION and therefore are not expected here.)
1562 : * 5) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
1563 : * argument's actual type as the function's return type.
1564 : * 6) If return type is ANYELEMENT, no argument is ANYELEMENT, but any argument
1565 : * is ANYARRAY or ANYRANGE, use the actual type of the argument to determine
1566 : * the function's return type, i.e. the array type's corresponding element
1567 : * type or the range type's corresponding subtype (or both, in which case
1568 : * they must match).
1569 : * 7) If return type is ANYELEMENT, no argument is ANYELEMENT, ANYARRAY, or
1570 : * ANYRANGE, generate an error. (This condition is prevented by CREATE
1571 : * FUNCTION and therefore is not expected here.)
1572 : * 8) ANYENUM is treated the same as ANYELEMENT except that if it is used
1573 : * (alone or in combination with plain ANYELEMENT), we add the extra
1574 : * condition that the ANYELEMENT type must be an enum.
1575 : * 9) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
1576 : * we add the extra condition that the ANYELEMENT type must not be an array.
1577 : * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
1578 : * is an extra restriction if not.)
1579 : *
1580 : * Domains over arrays or ranges match ANYARRAY or ANYRANGE arguments,
1581 : * respectively, and are immediately flattened to their base type. (In
1582 : * particular, if the return type is also ANYARRAY or ANYRANGE, we'll set it
1583 : * to the base type not the domain type.)
1584 : *
1585 : * When allow_poly is false, we are not expecting any of the actual_arg_types
1586 : * to be polymorphic, and we should not return a polymorphic result type
1587 : * either. When allow_poly is true, it is okay to have polymorphic "actual"
1588 : * arg types, and we can return ANYARRAY, ANYRANGE, or ANYELEMENT as the
1589 : * result. (This case is currently used only to check compatibility of an
1590 : * aggregate's declaration with the underlying transfn.)
1591 : *
1592 : * A special case is that we could see ANYARRAY as an actual_arg_type even
1593 : * when allow_poly is false (this is possible only because pg_statistic has
1594 : * columns shown as anyarray in the catalogs). We allow this to match a
1595 : * declared ANYARRAY argument, but only if there is no ANYELEMENT argument
1596 : * or result (since we can't determine a specific element type to match to
1597 : * ANYELEMENT). Note this means that functions taking ANYARRAY had better
1598 : * behave sanely if applied to the pg_statistic columns; they can't just
1599 : * assume that successive inputs are of the same actual element type.
1600 : */
1601 : Oid
1602 38018 : enforce_generic_type_consistency(Oid *actual_arg_types,
1603 : Oid *declared_arg_types,
1604 : int nargs,
1605 : Oid rettype,
1606 : bool allow_poly)
1607 : {
1608 : int j;
1609 38018 : bool have_generics = false;
1610 38018 : bool have_unknowns = false;
1611 38018 : Oid elem_typeid = InvalidOid;
1612 38018 : Oid array_typeid = InvalidOid;
1613 38018 : Oid range_typeid = InvalidOid;
1614 : Oid array_typelem;
1615 : Oid range_typelem;
1616 75228 : bool have_anyelement = (rettype == ANYELEMENTOID ||
1617 75228 : rettype == ANYNONARRAYOID ||
1618 : rettype == ANYENUMOID);
1619 38018 : bool have_anynonarray = (rettype == ANYNONARRAYOID);
1620 38018 : bool have_anyenum = (rettype == ANYENUMOID);
1621 :
1622 : /*
1623 : * Loop through the arguments to see if we have any that are polymorphic.
1624 : * If so, require the actual types to be consistent.
1625 : */
1626 99100 : for (j = 0; j < nargs; j++)
1627 : {
1628 61082 : Oid decl_type = declared_arg_types[j];
1629 61082 : Oid actual_type = actual_arg_types[j];
1630 :
1631 61082 : if (decl_type == ANYELEMENTOID ||
1632 59280 : decl_type == ANYNONARRAYOID ||
1633 : decl_type == ANYENUMOID)
1634 : {
1635 1907 : have_generics = have_anyelement = true;
1636 1907 : if (decl_type == ANYNONARRAYOID)
1637 1073 : have_anynonarray = true;
1638 834 : else if (decl_type == ANYENUMOID)
1639 105 : have_anyenum = true;
1640 1907 : if (actual_type == UNKNOWNOID)
1641 : {
1642 72 : have_unknowns = true;
1643 72 : continue;
1644 : }
1645 1835 : if (allow_poly && decl_type == actual_type)
1646 22 : continue; /* no new information here */
1647 1813 : if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
1648 0 : ereport(ERROR,
1649 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1650 : errmsg("arguments declared \"anyelement\" are not all alike"),
1651 : errdetail("%s versus %s",
1652 : format_type_be(elem_typeid),
1653 : format_type_be(actual_type))));
1654 1813 : elem_typeid = actual_type;
1655 : }
1656 59175 : else if (decl_type == ANYARRAYOID)
1657 : {
1658 2841 : have_generics = true;
1659 2841 : if (actual_type == UNKNOWNOID)
1660 : {
1661 594 : have_unknowns = true;
1662 594 : continue;
1663 : }
1664 2247 : if (allow_poly && decl_type == actual_type)
1665 10 : continue; /* no new information here */
1666 2237 : actual_type = getBaseType(actual_type); /* flatten domains */
1667 2237 : if (OidIsValid(array_typeid) && actual_type != array_typeid)
1668 0 : ereport(ERROR,
1669 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1670 : errmsg("arguments declared \"anyarray\" are not all alike"),
1671 : errdetail("%s versus %s",
1672 : format_type_be(array_typeid),
1673 : format_type_be(actual_type))));
1674 2237 : array_typeid = actual_type;
1675 : }
1676 56334 : else if (decl_type == ANYRANGEOID)
1677 : {
1678 422 : have_generics = true;
1679 422 : if (actual_type == UNKNOWNOID)
1680 : {
1681 7 : have_unknowns = true;
1682 7 : continue;
1683 : }
1684 415 : if (allow_poly && decl_type == actual_type)
1685 0 : continue; /* no new information here */
1686 415 : actual_type = getBaseType(actual_type); /* flatten domains */
1687 415 : if (OidIsValid(range_typeid) && actual_type != range_typeid)
1688 0 : ereport(ERROR,
1689 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1690 : errmsg("arguments declared \"anyrange\" are not all alike"),
1691 : errdetail("%s versus %s",
1692 : format_type_be(range_typeid),
1693 : format_type_be(actual_type))));
1694 415 : range_typeid = actual_type;
1695 : }
1696 : }
1697 :
1698 : /*
1699 : * Fast Track: if none of the arguments are polymorphic, return the
1700 : * unmodified rettype. We assume it can't be polymorphic either.
1701 : */
1702 38018 : if (!have_generics)
1703 34070 : return rettype;
1704 :
1705 : /* Get the element type based on the array type, if we have one */
1706 3948 : if (OidIsValid(array_typeid))
1707 : {
1708 2031 : if (array_typeid == ANYARRAYOID && !have_anyelement)
1709 : {
1710 : /* Special case for ANYARRAY input: okay iff no ANYELEMENT */
1711 3 : array_typelem = ANYELEMENTOID;
1712 : }
1713 : else
1714 : {
1715 2028 : array_typelem = get_element_type(array_typeid);
1716 2028 : if (!OidIsValid(array_typelem))
1717 0 : ereport(ERROR,
1718 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1719 : errmsg("argument declared %s is not an array but type %s",
1720 : "anyarray", format_type_be(array_typeid))));
1721 : }
1722 :
1723 2031 : if (!OidIsValid(elem_typeid))
1724 : {
1725 : /*
1726 : * if we don't have an element type yet, use the one we just got
1727 : */
1728 1951 : elem_typeid = array_typelem;
1729 : }
1730 80 : else if (array_typelem != elem_typeid)
1731 : {
1732 : /* otherwise, they better match */
1733 0 : ereport(ERROR,
1734 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1735 : errmsg("argument declared %s is not consistent with argument declared %s",
1736 : "anyarray", "anyelement"),
1737 : errdetail("%s versus %s",
1738 : format_type_be(array_typeid),
1739 : format_type_be(elem_typeid))));
1740 : }
1741 : }
1742 :
1743 : /* Get the element type based on the range type, if we have one */
1744 3948 : if (OidIsValid(range_typeid))
1745 : {
1746 236 : if (range_typeid == ANYRANGEOID && !have_anyelement)
1747 : {
1748 : /* Special case for ANYRANGE input: okay iff no ANYELEMENT */
1749 0 : range_typelem = ANYELEMENTOID;
1750 : }
1751 : else
1752 : {
1753 236 : range_typelem = get_range_subtype(range_typeid);
1754 236 : if (!OidIsValid(range_typelem))
1755 0 : ereport(ERROR,
1756 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1757 : errmsg("argument declared %s is not a range type but type %s",
1758 : "anyrange",
1759 : format_type_be(range_typeid))));
1760 : }
1761 :
1762 236 : if (!OidIsValid(elem_typeid))
1763 : {
1764 : /*
1765 : * if we don't have an element type yet, use the one we just got
1766 : */
1767 213 : elem_typeid = range_typelem;
1768 : }
1769 23 : else if (range_typelem != elem_typeid)
1770 : {
1771 : /* otherwise, they better match */
1772 0 : ereport(ERROR,
1773 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1774 : errmsg("argument declared %s is not consistent with argument declared %s",
1775 : "anyrange", "anyelement"),
1776 : errdetail("%s versus %s",
1777 : format_type_be(range_typeid),
1778 : format_type_be(elem_typeid))));
1779 : }
1780 : }
1781 :
1782 3948 : if (!OidIsValid(elem_typeid))
1783 : {
1784 24 : if (allow_poly)
1785 : {
1786 23 : elem_typeid = ANYELEMENTOID;
1787 23 : array_typeid = ANYARRAYOID;
1788 23 : range_typeid = ANYRANGEOID;
1789 : }
1790 : else
1791 : {
1792 : /* Only way to get here is if all the generic args are UNKNOWN */
1793 1 : ereport(ERROR,
1794 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1795 : errmsg("could not determine polymorphic type because input has type %s",
1796 : "unknown")));
1797 : }
1798 : }
1799 :
1800 3947 : if (have_anynonarray && elem_typeid != ANYELEMENTOID)
1801 : {
1802 : /* require the element type to not be an array or domain over array */
1803 1073 : if (type_is_array_domain(elem_typeid))
1804 0 : ereport(ERROR,
1805 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1806 : errmsg("type matched to anynonarray is an array type: %s",
1807 : format_type_be(elem_typeid))));
1808 : }
1809 :
1810 3947 : if (have_anyenum && elem_typeid != ANYELEMENTOID)
1811 : {
1812 : /* require the element type to be an enum */
1813 77 : if (!type_is_enum(elem_typeid))
1814 0 : ereport(ERROR,
1815 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1816 : errmsg("type matched to anyenum is not an enum type: %s",
1817 : format_type_be(elem_typeid))));
1818 : }
1819 :
1820 : /*
1821 : * If we had any unknown inputs, re-scan to assign correct types
1822 : */
1823 3947 : if (have_unknowns)
1824 : {
1825 2036 : for (j = 0; j < nargs; j++)
1826 : {
1827 1368 : Oid decl_type = declared_arg_types[j];
1828 1368 : Oid actual_type = actual_arg_types[j];
1829 :
1830 1368 : if (actual_type != UNKNOWNOID)
1831 695 : continue;
1832 :
1833 673 : if (decl_type == ANYELEMENTOID ||
1834 624 : decl_type == ANYNONARRAYOID ||
1835 : decl_type == ANYENUMOID)
1836 71 : declared_arg_types[j] = elem_typeid;
1837 602 : else if (decl_type == ANYARRAYOID)
1838 : {
1839 594 : if (!OidIsValid(array_typeid))
1840 : {
1841 4 : array_typeid = get_array_type(elem_typeid);
1842 4 : if (!OidIsValid(array_typeid))
1843 0 : ereport(ERROR,
1844 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1845 : errmsg("could not find array type for data type %s",
1846 : format_type_be(elem_typeid))));
1847 : }
1848 594 : declared_arg_types[j] = array_typeid;
1849 : }
1850 8 : else if (decl_type == ANYRANGEOID)
1851 : {
1852 7 : if (!OidIsValid(range_typeid))
1853 : {
1854 0 : ereport(ERROR,
1855 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1856 : errmsg("could not find range type for data type %s",
1857 : format_type_be(elem_typeid))));
1858 : }
1859 7 : declared_arg_types[j] = range_typeid;
1860 : }
1861 : }
1862 : }
1863 :
1864 : /* if we return ANYARRAY use the appropriate argument type */
1865 3947 : if (rettype == ANYARRAYOID)
1866 : {
1867 1379 : if (!OidIsValid(array_typeid))
1868 : {
1869 1065 : array_typeid = get_array_type(elem_typeid);
1870 1065 : if (!OidIsValid(array_typeid))
1871 0 : ereport(ERROR,
1872 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1873 : errmsg("could not find array type for data type %s",
1874 : format_type_be(elem_typeid))));
1875 : }
1876 1379 : return array_typeid;
1877 : }
1878 :
1879 : /* if we return ANYRANGE use the appropriate argument type */
1880 2568 : if (rettype == ANYRANGEOID)
1881 : {
1882 14 : if (!OidIsValid(range_typeid))
1883 : {
1884 0 : ereport(ERROR,
1885 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1886 : errmsg("could not find range type for data type %s",
1887 : format_type_be(elem_typeid))));
1888 : }
1889 14 : return range_typeid;
1890 : }
1891 :
1892 : /* if we return ANYELEMENT use the appropriate argument type */
1893 2554 : if (rettype == ANYELEMENTOID ||
1894 1746 : rettype == ANYNONARRAYOID ||
1895 : rettype == ANYENUMOID)
1896 846 : return elem_typeid;
1897 :
1898 : /* we don't return a generic type; send back the original return type */
1899 1708 : return rettype;
1900 : }
1901 :
1902 : /*
1903 : * resolve_generic_type()
1904 : * Deduce an individual actual datatype on the assumption that
1905 : * the rules for polymorphic types are being followed.
1906 : *
1907 : * declared_type is the declared datatype we want to resolve.
1908 : * context_actual_type is the actual input datatype to some argument
1909 : * that has declared datatype context_declared_type.
1910 : *
1911 : * If declared_type isn't polymorphic, we just return it. Otherwise,
1912 : * context_declared_type must be polymorphic, and we deduce the correct
1913 : * return type based on the relationship of the two polymorphic types.
1914 : */
1915 : Oid
1916 35 : resolve_generic_type(Oid declared_type,
1917 : Oid context_actual_type,
1918 : Oid context_declared_type)
1919 : {
1920 35 : if (declared_type == ANYARRAYOID)
1921 : {
1922 12 : if (context_declared_type == ANYARRAYOID)
1923 : {
1924 : /*
1925 : * Use actual type, but it must be an array; or if it's a domain
1926 : * over array, use the base array type.
1927 : */
1928 0 : Oid context_base_type = getBaseType(context_actual_type);
1929 0 : Oid array_typelem = get_element_type(context_base_type);
1930 :
1931 0 : if (!OidIsValid(array_typelem))
1932 0 : ereport(ERROR,
1933 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1934 : errmsg("argument declared %s is not an array but type %s",
1935 : "anyarray", format_type_be(context_base_type))));
1936 0 : return context_base_type;
1937 : }
1938 12 : else if (context_declared_type == ANYELEMENTOID ||
1939 0 : context_declared_type == ANYNONARRAYOID ||
1940 0 : context_declared_type == ANYENUMOID ||
1941 : context_declared_type == ANYRANGEOID)
1942 : {
1943 : /* Use the array type corresponding to actual type */
1944 12 : Oid array_typeid = get_array_type(context_actual_type);
1945 :
1946 12 : if (!OidIsValid(array_typeid))
1947 0 : ereport(ERROR,
1948 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1949 : errmsg("could not find array type for data type %s",
1950 : format_type_be(context_actual_type))));
1951 12 : return array_typeid;
1952 : }
1953 : }
1954 23 : else if (declared_type == ANYELEMENTOID ||
1955 0 : declared_type == ANYNONARRAYOID ||
1956 0 : declared_type == ANYENUMOID ||
1957 : declared_type == ANYRANGEOID)
1958 : {
1959 23 : if (context_declared_type == ANYARRAYOID)
1960 : {
1961 : /* Use the element type corresponding to actual type */
1962 20 : Oid context_base_type = getBaseType(context_actual_type);
1963 20 : Oid array_typelem = get_element_type(context_base_type);
1964 :
1965 20 : if (!OidIsValid(array_typelem))
1966 0 : ereport(ERROR,
1967 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1968 : errmsg("argument declared %s is not an array but type %s",
1969 : "anyarray", format_type_be(context_base_type))));
1970 20 : return array_typelem;
1971 : }
1972 3 : else if (context_declared_type == ANYRANGEOID)
1973 : {
1974 : /* Use the element type corresponding to actual type */
1975 3 : Oid context_base_type = getBaseType(context_actual_type);
1976 3 : Oid range_typelem = get_range_subtype(context_base_type);
1977 :
1978 3 : if (!OidIsValid(range_typelem))
1979 0 : ereport(ERROR,
1980 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1981 : errmsg("argument declared %s is not a range type but type %s",
1982 : "anyrange", format_type_be(context_base_type))));
1983 3 : return range_typelem;
1984 : }
1985 0 : else if (context_declared_type == ANYELEMENTOID ||
1986 0 : context_declared_type == ANYNONARRAYOID ||
1987 : context_declared_type == ANYENUMOID)
1988 : {
1989 : /* Use the actual type; it doesn't matter if array or not */
1990 0 : return context_actual_type;
1991 : }
1992 : }
1993 : else
1994 : {
1995 : /* declared_type isn't polymorphic, so return it as-is */
1996 0 : return declared_type;
1997 : }
1998 : /* If we get here, declared_type is polymorphic and context isn't */
1999 : /* NB: this is a calling-code logic error, not a user error */
2000 0 : elog(ERROR, "could not determine polymorphic type because context isn't polymorphic");
2001 : return InvalidOid; /* keep compiler quiet */
2002 : }
2003 :
2004 :
2005 : /* TypeCategory()
2006 : * Assign a category to the specified type OID.
2007 : *
2008 : * NB: this must not return TYPCATEGORY_INVALID.
2009 : */
2010 : TYPCATEGORY
2011 5093 : TypeCategory(Oid type)
2012 : {
2013 : char typcategory;
2014 : bool typispreferred;
2015 :
2016 5093 : get_type_category_preferred(type, &typcategory, &typispreferred);
2017 5093 : Assert(typcategory != TYPCATEGORY_INVALID);
2018 5093 : return (TYPCATEGORY) typcategory;
2019 : }
2020 :
2021 :
2022 : /* IsPreferredType()
2023 : * Check if this type is a preferred type for the given category.
2024 : *
2025 : * If category is TYPCATEGORY_INVALID, then we'll return TRUE for preferred
2026 : * types of any category; otherwise, only for preferred types of that
2027 : * category.
2028 : */
2029 : bool
2030 937 : IsPreferredType(TYPCATEGORY category, Oid type)
2031 : {
2032 : char typcategory;
2033 : bool typispreferred;
2034 :
2035 937 : get_type_category_preferred(type, &typcategory, &typispreferred);
2036 937 : if (category == typcategory || category == TYPCATEGORY_INVALID)
2037 787 : return typispreferred;
2038 : else
2039 150 : return false;
2040 : }
2041 :
2042 :
2043 : /* IsBinaryCoercible()
2044 : * Check if srctype is binary-coercible to targettype.
2045 : *
2046 : * This notion allows us to cheat and directly exchange values without
2047 : * going through the trouble of calling a conversion function. Note that
2048 : * in general, this should only be an implementation shortcut. Before 7.4,
2049 : * this was also used as a heuristic for resolving overloaded functions and
2050 : * operators, but that's basically a bad idea.
2051 : *
2052 : * As of 7.3, binary coercibility isn't hardwired into the code anymore.
2053 : * We consider two types binary-coercible if there is an implicitly
2054 : * invokable, no-function-needed pg_cast entry. Also, a domain is always
2055 : * binary-coercible to its base type, though *not* vice versa (in the other
2056 : * direction, one must apply domain constraint checks before accepting the
2057 : * value as legitimate). We also need to special-case various polymorphic
2058 : * types.
2059 : *
2060 : * This function replaces IsBinaryCompatible(), which was an inherently
2061 : * symmetric test. Since the pg_cast entries aren't necessarily symmetric,
2062 : * the order of the operands is now significant.
2063 : */
2064 : bool
2065 56131 : IsBinaryCoercible(Oid srctype, Oid targettype)
2066 : {
2067 : HeapTuple tuple;
2068 : Form_pg_cast castForm;
2069 : bool result;
2070 :
2071 : /* Fast path if same type */
2072 56131 : if (srctype == targettype)
2073 21887 : return true;
2074 :
2075 : /* Anything is coercible to ANY or ANYELEMENT */
2076 34244 : if (targettype == ANYOID || targettype == ANYELEMENTOID)
2077 12 : return true;
2078 :
2079 : /* If srctype is a domain, reduce to its base type */
2080 34232 : if (OidIsValid(srctype))
2081 34232 : srctype = getBaseType(srctype);
2082 :
2083 : /* Somewhat-fast path for domain -> base type case */
2084 34232 : if (srctype == targettype)
2085 3 : return true;
2086 :
2087 : /* Also accept any array type as coercible to ANYARRAY */
2088 34229 : if (targettype == ANYARRAYOID)
2089 1830 : if (type_is_array(srctype))
2090 55 : return true;
2091 :
2092 : /* Also accept any non-array type as coercible to ANYNONARRAY */
2093 34174 : if (targettype == ANYNONARRAYOID)
2094 0 : if (!type_is_array(srctype))
2095 0 : return true;
2096 :
2097 : /* Also accept any enum type as coercible to ANYENUM */
2098 34174 : if (targettype == ANYENUMOID)
2099 1681 : if (type_is_enum(srctype))
2100 7 : return true;
2101 :
2102 : /* Also accept any range type as coercible to ANYRANGE */
2103 34167 : if (targettype == ANYRANGEOID)
2104 546 : if (type_is_range(srctype))
2105 23 : return true;
2106 :
2107 : /* Also accept any composite type as coercible to RECORD */
2108 34144 : if (targettype == RECORDOID)
2109 391 : if (ISCOMPLEX(srctype))
2110 10 : return true;
2111 :
2112 : /* Also accept any composite array type as coercible to RECORD[] */
2113 34134 : if (targettype == RECORDARRAYOID)
2114 0 : if (is_complex_array(srctype))
2115 0 : return true;
2116 :
2117 : /* Else look in pg_cast */
2118 34134 : tuple = SearchSysCache2(CASTSOURCETARGET,
2119 : ObjectIdGetDatum(srctype),
2120 : ObjectIdGetDatum(targettype));
2121 34134 : if (!HeapTupleIsValid(tuple))
2122 26972 : return false; /* no cast */
2123 7162 : castForm = (Form_pg_cast) GETSTRUCT(tuple);
2124 :
2125 8432 : result = (castForm->castmethod == COERCION_METHOD_BINARY &&
2126 1270 : castForm->castcontext == COERCION_CODE_IMPLICIT);
2127 :
2128 7162 : ReleaseSysCache(tuple);
2129 :
2130 7162 : return result;
2131 : }
2132 :
2133 :
2134 : /*
2135 : * find_coercion_pathway
2136 : * Look for a coercion pathway between two types.
2137 : *
2138 : * Currently, this deals only with scalar-type cases; it does not consider
2139 : * polymorphic types nor casts between composite types. (Perhaps fold
2140 : * those in someday?)
2141 : *
2142 : * ccontext determines the set of available casts.
2143 : *
2144 : * The possible result codes are:
2145 : * COERCION_PATH_NONE: failed to find any coercion pathway
2146 : * *funcid is set to InvalidOid
2147 : * COERCION_PATH_FUNC: apply the coercion function returned in *funcid
2148 : * COERCION_PATH_RELABELTYPE: binary-compatible cast, no function needed
2149 : * *funcid is set to InvalidOid
2150 : * COERCION_PATH_ARRAYCOERCE: need an ArrayCoerceExpr node
2151 : * *funcid is set to the element cast function, or InvalidOid
2152 : * if the array elements are binary-compatible
2153 : * COERCION_PATH_COERCEVIAIO: need a CoerceViaIO node
2154 : * *funcid is set to InvalidOid
2155 : *
2156 : * Note: COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
2157 : * needed to do the coercion; if the target is a domain then we may need to
2158 : * apply domain constraint checking. If you want to check for a zero-effort
2159 : * conversion then use IsBinaryCoercible().
2160 : */
2161 : CoercionPathType
2162 43112 : find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
2163 : CoercionContext ccontext,
2164 : Oid *funcid)
2165 : {
2166 43112 : CoercionPathType result = COERCION_PATH_NONE;
2167 : HeapTuple tuple;
2168 :
2169 43112 : *funcid = InvalidOid;
2170 :
2171 : /* Perhaps the types are domains; if so, look at their base types */
2172 43112 : if (OidIsValid(sourceTypeId))
2173 43112 : sourceTypeId = getBaseType(sourceTypeId);
2174 43112 : if (OidIsValid(targetTypeId))
2175 43112 : targetTypeId = getBaseType(targetTypeId);
2176 :
2177 : /* Domains are always coercible to and from their base type */
2178 43112 : if (sourceTypeId == targetTypeId)
2179 479 : return COERCION_PATH_RELABELTYPE;
2180 :
2181 : /* Look in pg_cast */
2182 42633 : tuple = SearchSysCache2(CASTSOURCETARGET,
2183 : ObjectIdGetDatum(sourceTypeId),
2184 : ObjectIdGetDatum(targetTypeId));
2185 :
2186 42633 : if (HeapTupleIsValid(tuple))
2187 : {
2188 16493 : Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
2189 : CoercionContext castcontext;
2190 :
2191 : /* convert char value for castcontext to CoercionContext enum */
2192 16493 : switch (castForm->castcontext)
2193 : {
2194 : case COERCION_CODE_IMPLICIT:
2195 11776 : castcontext = COERCION_IMPLICIT;
2196 11776 : break;
2197 : case COERCION_CODE_ASSIGNMENT:
2198 4178 : castcontext = COERCION_ASSIGNMENT;
2199 4178 : break;
2200 : case COERCION_CODE_EXPLICIT:
2201 539 : castcontext = COERCION_EXPLICIT;
2202 539 : break;
2203 : default:
2204 0 : elog(ERROR, "unrecognized castcontext: %d",
2205 : (int) castForm->castcontext);
2206 : castcontext = 0; /* keep compiler quiet */
2207 : break;
2208 : }
2209 :
2210 : /* Rely on ordering of enum for correct behavior here */
2211 16493 : if (ccontext >= castcontext)
2212 : {
2213 13298 : switch (castForm->castmethod)
2214 : {
2215 : case COERCION_METHOD_FUNCTION:
2216 7334 : result = COERCION_PATH_FUNC;
2217 7334 : *funcid = castForm->castfunc;
2218 7334 : break;
2219 : case COERCION_METHOD_INOUT:
2220 2 : result = COERCION_PATH_COERCEVIAIO;
2221 2 : break;
2222 : case COERCION_METHOD_BINARY:
2223 5962 : result = COERCION_PATH_RELABELTYPE;
2224 5962 : break;
2225 : default:
2226 0 : elog(ERROR, "unrecognized castmethod: %d",
2227 : (int) castForm->castmethod);
2228 : break;
2229 : }
2230 : }
2231 :
2232 16493 : ReleaseSysCache(tuple);
2233 : }
2234 : else
2235 : {
2236 : /*
2237 : * If there's no pg_cast entry, perhaps we are dealing with a pair of
2238 : * array types. If so, and if the element types have a suitable cast,
2239 : * report that we can coerce with an ArrayCoerceExpr.
2240 : *
2241 : * Note that the source type can be a domain over array, but not the
2242 : * target, because ArrayCoerceExpr won't check domain constraints.
2243 : *
2244 : * Hack: disallow coercions to oidvector and int2vector, which
2245 : * otherwise tend to capture coercions that should go to "real" array
2246 : * types. We want those types to be considered "real" arrays for many
2247 : * purposes, but not this one. (Also, ArrayCoerceExpr isn't
2248 : * guaranteed to produce an output that meets the restrictions of
2249 : * these datatypes, such as being 1-dimensional.)
2250 : */
2251 26140 : if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
2252 : {
2253 : Oid targetElem;
2254 : Oid sourceElem;
2255 :
2256 25791 : if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
2257 : (sourceElem = get_base_element_type(sourceTypeId)) != InvalidOid)
2258 : {
2259 : CoercionPathType elempathtype;
2260 : Oid elemfuncid;
2261 :
2262 117 : elempathtype = find_coercion_pathway(targetElem,
2263 : sourceElem,
2264 : ccontext,
2265 : &elemfuncid);
2266 117 : if (elempathtype != COERCION_PATH_NONE &&
2267 : elempathtype != COERCION_PATH_ARRAYCOERCE)
2268 : {
2269 73 : *funcid = elemfuncid;
2270 73 : if (elempathtype == COERCION_PATH_COERCEVIAIO)
2271 10 : result = COERCION_PATH_COERCEVIAIO;
2272 : else
2273 63 : result = COERCION_PATH_ARRAYCOERCE;
2274 : }
2275 : }
2276 : }
2277 :
2278 : /*
2279 : * If we still haven't found a possibility, consider automatic casting
2280 : * using I/O functions. We allow assignment casts to string types and
2281 : * explicit casts from string types to be handled this way. (The
2282 : * CoerceViaIO mechanism is a lot more general than that, but this is
2283 : * all we want to allow in the absence of a pg_cast entry.) It would
2284 : * probably be better to insist on explicit casts in both directions,
2285 : * but this is a compromise to preserve something of the pre-8.3
2286 : * behavior that many types had implicit (yipes!) casts to text.
2287 : */
2288 26140 : if (result == COERCION_PATH_NONE)
2289 : {
2290 27814 : if (ccontext >= COERCION_ASSIGNMENT &&
2291 1747 : TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
2292 1406 : result = COERCION_PATH_COERCEVIAIO;
2293 24969 : else if (ccontext >= COERCION_EXPLICIT &&
2294 308 : TypeCategory(sourceTypeId) == TYPCATEGORY_STRING)
2295 98 : result = COERCION_PATH_COERCEVIAIO;
2296 : }
2297 : }
2298 :
2299 42633 : return result;
2300 : }
2301 :
2302 :
2303 : /*
2304 : * find_typmod_coercion_function -- does the given type need length coercion?
2305 : *
2306 : * If the target type possesses a pg_cast function from itself to itself,
2307 : * it must need length coercion.
2308 : *
2309 : * "bpchar" (ie, char(N)) and "numeric" are examples of such types.
2310 : *
2311 : * If the given type is a varlena array type, we do not look for a coercion
2312 : * function associated directly with the array type, but instead look for
2313 : * one associated with the element type. An ArrayCoerceExpr node must be
2314 : * used to apply such a function.
2315 : *
2316 : * We use the same result enum as find_coercion_pathway, but the only possible
2317 : * result codes are:
2318 : * COERCION_PATH_NONE: no length coercion needed
2319 : * COERCION_PATH_FUNC: apply the function returned in *funcid
2320 : * COERCION_PATH_ARRAYCOERCE: apply the function using ArrayCoerceExpr
2321 : */
2322 : CoercionPathType
2323 1675 : find_typmod_coercion_function(Oid typeId,
2324 : Oid *funcid)
2325 : {
2326 : CoercionPathType result;
2327 : Type targetType;
2328 : Form_pg_type typeForm;
2329 : HeapTuple tuple;
2330 :
2331 1675 : *funcid = InvalidOid;
2332 1675 : result = COERCION_PATH_FUNC;
2333 :
2334 1675 : targetType = typeidType(typeId);
2335 1675 : typeForm = (Form_pg_type) GETSTRUCT(targetType);
2336 :
2337 : /* Check for a varlena array type */
2338 1675 : if (typeForm->typelem != InvalidOid && typeForm->typlen == -1)
2339 : {
2340 : /* Yes, switch our attention to the element type */
2341 14 : typeId = typeForm->typelem;
2342 14 : result = COERCION_PATH_ARRAYCOERCE;
2343 : }
2344 1675 : ReleaseSysCache(targetType);
2345 :
2346 : /* Look in pg_cast */
2347 1675 : tuple = SearchSysCache2(CASTSOURCETARGET,
2348 : ObjectIdGetDatum(typeId),
2349 : ObjectIdGetDatum(typeId));
2350 :
2351 1675 : if (HeapTupleIsValid(tuple))
2352 : {
2353 1675 : Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
2354 :
2355 1675 : *funcid = castForm->castfunc;
2356 1675 : ReleaseSysCache(tuple);
2357 : }
2358 :
2359 1675 : if (!OidIsValid(*funcid))
2360 0 : result = COERCION_PATH_NONE;
2361 :
2362 1675 : return result;
2363 : }
2364 :
2365 : /*
2366 : * is_complex_array
2367 : * Is this type an array of composite?
2368 : *
2369 : * Note: this will not return true for record[]; check for RECORDARRAYOID
2370 : * separately if needed.
2371 : */
2372 : static bool
2373 2 : is_complex_array(Oid typid)
2374 : {
2375 2 : Oid elemtype = get_element_type(typid);
2376 :
2377 2 : return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
2378 : }
2379 :
2380 :
2381 : /*
2382 : * Check whether reltypeId is the row type of a typed table of type
2383 : * reloftypeId. (This is conceptually similar to the subtype
2384 : * relationship checked by typeInheritsFrom().)
2385 : */
2386 : static bool
2387 27349 : typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
2388 : {
2389 27349 : Oid relid = typeidTypeRelid(reltypeId);
2390 27349 : bool result = false;
2391 :
2392 27349 : if (relid)
2393 : {
2394 : HeapTuple tp;
2395 : Form_pg_class reltup;
2396 :
2397 603 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2398 603 : if (!HeapTupleIsValid(tp))
2399 0 : elog(ERROR, "cache lookup failed for relation %u", relid);
2400 :
2401 603 : reltup = (Form_pg_class) GETSTRUCT(tp);
2402 603 : if (reltup->reloftype == reloftypeId)
2403 2 : result = true;
2404 :
2405 603 : ReleaseSysCache(tp);
2406 : }
2407 :
2408 27349 : return result;
2409 : }
|