Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * parse_coerce.c
4 : : * handle type coercions/conversions for parser
5 : : *
6 : : * Portions Copyright (c) 1996-2024, 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 "catalog/pg_cast.h"
18 : : #include "catalog/pg_class.h"
19 : : #include "catalog/pg_inherits.h"
20 : : #include "catalog/pg_proc.h"
21 : : #include "catalog/pg_type.h"
22 : : #include "nodes/makefuncs.h"
23 : : #include "nodes/nodeFuncs.h"
24 : : #include "parser/parse_coerce.h"
25 : : #include "parser/parse_relation.h"
26 : : #include "parser/parse_type.h"
27 : : #include "utils/builtins.h"
28 : : #include "utils/datum.h" /* needed for datumIsEqual() */
29 : : #include "utils/fmgroids.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 : : CoercionContext ccontext, CoercionForm cformat,
38 : : int location,
39 : : bool hideInputCoercion);
40 : : static void hide_coercion_node(Node *node);
41 : : static Node *build_coercion_expression(Node *node,
42 : : CoercionPathType pathtype,
43 : : Oid funcId,
44 : : Oid targetTypeId, int32 targetTypMod,
45 : : CoercionContext ccontext, CoercionForm cformat,
46 : : int location);
47 : : static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
48 : : Oid targetTypeId,
49 : : CoercionContext ccontext,
50 : : CoercionForm cformat,
51 : : int location);
52 : : static bool is_complex_array(Oid typid);
53 : : static bool typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId);
54 : :
55 : :
56 : : /*
57 : : * coerce_to_target_type()
58 : : * Convert an expression to a target type and typmod.
59 : : *
60 : : * This is the general-purpose entry point for arbitrary type coercion
61 : : * operations. Direct use of the component operations can_coerce_type,
62 : : * coerce_type, and coerce_type_typmod should be restricted to special
63 : : * cases (eg, when the conversion is expected to succeed).
64 : : *
65 : : * Returns the possibly-transformed expression tree, or NULL if the type
66 : : * conversion is not possible. (We do this, rather than ereport'ing directly,
67 : : * so that callers can generate custom error messages indicating context.)
68 : : *
69 : : * pstate - parse state (can be NULL, see coerce_type)
70 : : * expr - input expression tree (already transformed by transformExpr)
71 : : * exprtype - result type of expr
72 : : * targettype - desired result type
73 : : * targettypmod - desired result typmod
74 : : * ccontext, cformat - context indicators to control coercions
75 : : * location - parse location of the coercion request, or -1 if unknown/implicit
76 : : */
77 : : Node *
7656 tgl@sss.pgh.pa.us 78 :CBC 354597 : coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
79 : : Oid targettype, int32 targettypmod,
80 : : CoercionContext ccontext,
81 : : CoercionForm cformat,
82 : : int location)
83 : : {
84 : : Node *result;
85 : : Node *origexpr;
86 : :
7242 87 [ + + ]: 354597 : if (!can_coerce_type(1, &exprtype, &targettype, ccontext))
88 : 277 : return NULL;
89 : :
90 : : /*
91 : : * If the input has a CollateExpr at the top, strip it off, perform the
92 : : * coercion, and put a new one back on. This is annoying since it
93 : : * duplicates logic in coerce_type, but if we don't do this then it's too
94 : : * hard to tell whether coerce_type actually changed anything, and we
95 : : * *must* know that to avoid possibly calling hide_coercion_node on
96 : : * something that wasn't generated by coerce_type. Note that if there are
97 : : * multiple stacked CollateExprs, we just discard all but the topmost.
98 : : * Also, if the target type isn't collatable, we discard the CollateExpr.
99 : : */
4486 100 : 354320 : origexpr = expr;
101 [ + - + + ]: 354335 : while (expr && IsA(expr, CollateExpr))
102 : 15 : expr = (Node *) ((CollateExpr *) expr)->arg;
103 : :
7242 104 : 354320 : result = coerce_type(pstate, expr, exprtype,
105 : : targettype, targettypmod,
106 : : ccontext, cformat, location);
107 : :
108 : : /*
109 : : * If the target is a fixed-length type, it may need a length coercion as
110 : : * well as a type coercion. If we find ourselves adding both, force the
111 : : * inner coercion node to implicit display form.
112 : : */
113 : 352149 : result = coerce_type_typmod(result,
114 : : targettype, targettypmod,
115 : : ccontext, cformat, location,
116 [ + + + + ]: 352149 : (result != expr && !IsA(result, Const)));
117 : :
1098 118 [ + + + + ]: 352149 : if (expr != origexpr && type_is_collatable(targettype))
119 : : {
120 : : /* Reinstall top CollateExpr */
4486 121 : 12 : CollateExpr *coll = (CollateExpr *) origexpr;
122 : 12 : CollateExpr *newcoll = makeNode(CollateExpr);
123 : :
124 : 12 : newcoll->arg = (Expr *) result;
125 : 12 : newcoll->collOid = coll->collOid;
126 : 12 : newcoll->location = coll->location;
127 : 12 : result = (Node *) newcoll;
128 : : }
129 : :
7242 130 : 352149 : return result;
131 : : }
132 : :
133 : :
134 : : /*
135 : : * coerce_type()
136 : : * Convert an expression to a different type.
137 : : *
138 : : * The caller should already have determined that the coercion is possible;
139 : : * see can_coerce_type.
140 : : *
141 : : * Normally, no coercion to a typmod (length) is performed here. The caller
142 : : * must call coerce_type_typmod as well, if a typmod constraint is wanted.
143 : : * (But if the target type is a domain, it may internally contain a
144 : : * typmod constraint, which will be applied inside coerce_to_domain.)
145 : : * In some cases pg_cast specifies a type coercion function that also
146 : : * applies length conversion, and in those cases only, the result will
147 : : * already be properly coerced to the specified typmod.
148 : : *
149 : : * pstate is only used in the case that we are able to resolve the type of
150 : : * a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
151 : : * caller does not want type information updated for Params.
152 : : *
153 : : * Note: this function must not modify the given expression tree, only add
154 : : * decoration on top of it. See transformSetOperationTree, for example.
155 : : */
156 : : Node *
7656 157 : 656067 : coerce_type(ParseState *pstate, Node *node,
158 : : Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
159 : : CoercionContext ccontext, CoercionForm cformat, int location)
160 : : {
161 : : Node *result;
162 : : CoercionPathType pathtype;
163 : : Oid funcId;
164 : :
8788 165 [ + + - + ]: 656067 : if (targetTypeId == inputTypeId ||
166 : : node == NULL)
167 : : {
168 : : /* no conversion needed */
7656 169 : 177714 : return node;
170 : : }
7424 171 [ + + + + ]: 478353 : if (targetTypeId == ANYOID ||
6395 172 [ + + ]: 470880 : targetTypeId == ANYELEMENTOID ||
1487 173 [ + - ]: 463194 : targetTypeId == ANYNONARRAYOID ||
174 [ - + ]: 463194 : targetTypeId == ANYCOMPATIBLEOID ||
175 : : targetTypeId == ANYCOMPATIBLENONARRAYOID)
176 : : {
177 : : /*
178 : : * Assume can_coerce_type verified that implicit coercion is okay.
179 : : *
180 : : * Note: by returning the unmodified node here, we are saying that
181 : : * it's OK to treat an UNKNOWN constant as a valid input for a
182 : : * function accepting one of these pseudotypes. This should be all
183 : : * right, since an UNKNOWN value is still a perfectly valid Datum.
184 : : *
185 : : * NB: we do NOT want a RelabelType here: the exposed type of the
186 : : * function argument must be its actual type, not the polymorphic
187 : : * pseudotype.
188 : : */
7424 189 : 15159 : return node;
190 : : }
4694 191 [ + + + + ]: 463194 : if (targetTypeId == ANYARRAYOID ||
4546 heikki.linnakangas@i 192 [ + + ]: 449178 : targetTypeId == ANYENUMOID ||
1487 tgl@sss.pgh.pa.us 193 [ + + ]: 445192 : targetTypeId == ANYRANGEOID ||
1211 akorotkov@postgresql 194 [ + - ]: 442746 : targetTypeId == ANYMULTIRANGEOID ||
1487 tgl@sss.pgh.pa.us 195 [ + - ]: 442746 : targetTypeId == ANYCOMPATIBLEARRAYOID ||
1211 akorotkov@postgresql 196 [ - + ]: 442746 : targetTypeId == ANYCOMPATIBLERANGEOID ||
197 : : targetTypeId == ANYCOMPATIBLEMULTIRANGEOID)
198 : : {
199 : : /*
200 : : * Assume can_coerce_type verified that implicit coercion is okay.
201 : : *
202 : : * These cases are unlike the ones above because the exposed type of
203 : : * the argument must be an actual array, enum, range, or multirange
204 : : * type. In particular the argument must *not* be an UNKNOWN
205 : : * constant. If it is, we just fall through; below, we'll call the
206 : : * pseudotype's input function, which will produce an error. Also, if
207 : : * what we have is a domain over array, enum, range, or multirange, we
208 : : * have to relabel it to its base type.
209 : : *
210 : : * Note: currently, we can't actually see a domain-over-enum here,
211 : : * since the other functions in this file will not match such a
212 : : * parameter to ANYENUM. But that should get changed eventually.
213 : : */
4694 tgl@sss.pgh.pa.us 214 [ + + ]: 20448 : if (inputTypeId != UNKNOWNOID)
215 : : {
216 : 19998 : Oid baseTypeId = getBaseType(inputTypeId);
217 : :
218 [ + + ]: 19998 : if (baseTypeId != inputTypeId)
219 : : {
220 : 27 : RelabelType *r = makeRelabelType((Expr *) node,
221 : : baseTypeId, -1,
222 : : InvalidOid,
223 : : cformat);
224 : :
225 : 27 : r->location = location;
226 : 27 : return (Node *) r;
227 : : }
228 : : /* Not a domain type, so return it as-is */
229 : 19971 : return node;
230 : : }
231 : : }
7656 232 [ + + + + ]: 443196 : if (inputTypeId == UNKNOWNOID && IsA(node, Const))
233 : : {
234 : : /*
235 : : * Input is a string constant with previously undetermined type. Apply
236 : : * the target type's typinput function to it to produce a constant of
237 : : * the target type.
238 : : *
239 : : * NOTE: this case cannot be folded together with the other
240 : : * constant-input case, since the typinput function does not
241 : : * necessarily behave the same as a type conversion function. For
242 : : * example, int4's typinput function will reject "1.2", whereas
243 : : * float-to-int type conversion will round to integer.
244 : : *
245 : : * XXX if the typinput function is not immutable, we really ought to
246 : : * postpone evaluation of the function call until runtime. But there
247 : : * is no way to represent a typinput function call as an expression
248 : : * tree, because C-string values are not Datums. (XXX This *is*
249 : : * possible as of 7.3, do we want to do it?)
250 : : */
9019 251 : 311698 : Const *con = (Const *) node;
9000 252 : 311698 : Const *newcon = makeNode(Const);
253 : : Oid baseTypeId;
254 : : int32 baseTypeMod;
255 : : int32 inputTypeMod;
256 : : Type baseType;
257 : : ParseCallbackState pcbstate;
258 : :
259 : : /*
260 : : * If the target type is a domain, we want to call its base type's
261 : : * input routine, not domain_in(). This is to avoid premature failure
262 : : * when the domain applies a typmod: existing input routines follow
263 : : * implicit-coercion semantics for length checks, which is not always
264 : : * what we want here. The needed check will be applied properly
265 : : * inside coerce_to_domain().
266 : : */
5695 267 : 311698 : baseTypeMod = targetTypeMod;
6584 268 : 311698 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
269 : :
270 : : /*
271 : : * For most types we pass typmod -1 to the input routine, because
272 : : * existing input routines follow implicit-coercion semantics for
273 : : * length checks, which is not always what we want here. Any length
274 : : * constraint will be applied later by our caller. An exception
275 : : * however is the INTERVAL type, for which we *must* pass the typmod
276 : : * or it won't be able to obey the bizarre SQL-spec input rules. (Ugly
277 : : * as sin, but so is this part of the spec...)
278 : : */
5695 279 [ + + ]: 311698 : if (baseTypeId == INTERVALOID)
280 : 2536 : inputTypeMod = baseTypeMod;
281 : : else
282 : 309162 : inputTypeMod = -1;
283 : :
3270 noah@leadboat.com 284 : 311698 : baseType = typeidType(baseTypeId);
285 : :
6584 tgl@sss.pgh.pa.us 286 : 311698 : newcon->consttype = baseTypeId;
5695 287 : 311698 : newcon->consttypmod = inputTypeMod;
3270 noah@leadboat.com 288 : 311698 : newcon->constcollid = typeTypeCollation(baseType);
289 : 311698 : newcon->constlen = typeLen(baseType);
290 : 311698 : newcon->constbyval = typeByVal(baseType);
9000 tgl@sss.pgh.pa.us 291 : 311698 : newcon->constisnull = con->constisnull;
292 : :
293 : : /*
294 : : * We use the original literal's location regardless of the position
295 : : * of the coercion. This is a change from pre-9.2 behavior, meant to
296 : : * simplify life for pg_stat_statements.
297 : : */
4401 298 : 311698 : newcon->location = con->location;
299 : :
300 : : /*
301 : : * Set up to point at the constant's text if the input routine throws
302 : : * an error.
303 : : */
5704 304 : 311698 : setup_parser_errposition_callback(&pcbstate, pstate, con->location);
305 : :
306 : : /*
307 : : * We assume here that UNKNOWN's internal representation is the same
308 : : * as CSTRING.
309 : : */
8768 bruce@momjian.us 310 [ + + ]: 311698 : if (!con->constisnull)
3270 noah@leadboat.com 311 : 280209 : newcon->constvalue = stringTypeDatum(baseType,
312 : : DatumGetCString(con->constvalue),
313 : : inputTypeMod);
314 : : else
315 : 31489 : newcon->constvalue = stringTypeDatum(baseType,
316 : : NULL,
317 : : inputTypeMod);
318 : :
319 : : /*
320 : : * If it's a varlena value, force it to be in non-expanded
321 : : * (non-toasted) format; this avoids any possible dependency on
322 : : * external values and improves consistency of representation.
323 : : */
3006 tgl@sss.pgh.pa.us 324 [ + + + + ]: 309417 : if (!con->constisnull && newcon->constlen == -1)
325 : 142305 : newcon->constvalue =
326 : 142305 : PointerGetDatum(PG_DETOAST_DATUM(newcon->constvalue));
327 : :
328 : : #ifdef RANDOMIZE_ALLOCATED_MEMORY
329 : :
330 : : /*
331 : : * For pass-by-reference data types, repeat the conversion to see if
332 : : * the input function leaves any uninitialized bytes in the result. We
333 : : * can only detect that reliably if RANDOMIZE_ALLOCATED_MEMORY is
334 : : * enabled, so we don't bother testing otherwise. The reason we don't
335 : : * want any instability in the input function is that comparison of
336 : : * Const nodes relies on bytewise comparison of the datums, so if the
337 : : * input function leaves garbage then subexpressions that should be
338 : : * identical may not get recognized as such. See pgsql-hackers
339 : : * discussion of 2008-04-04.
340 : : */
341 : : if (!con->constisnull && !newcon->constbyval)
342 : : {
343 : : Datum val2;
344 : :
345 : : val2 = stringTypeDatum(baseType,
346 : : DatumGetCString(con->constvalue),
347 : : inputTypeMod);
348 : : if (newcon->constlen == -1)
349 : : val2 = PointerGetDatum(PG_DETOAST_DATUM(val2));
350 : : if (!datumIsEqual(newcon->constvalue, val2, false, newcon->constlen))
351 : : elog(WARNING, "type %s has unstable input conversion for \"%s\"",
352 : : typeTypeName(baseType), DatumGetCString(con->constvalue));
353 : : }
354 : : #endif
355 : :
5704 356 : 309417 : cancel_parser_errposition_callback(&pcbstate);
357 : :
9000 358 : 309417 : result = (Node *) newcon;
359 : :
360 : : /* If target is a domain, apply constraints. */
6584 361 [ + + ]: 309417 : if (baseTypeId != targetTypeId)
362 : 13156 : result = coerce_to_domain(result,
363 : : baseTypeId, baseTypeMod,
364 : : targetTypeId,
365 : : ccontext, cformat, location,
366 : : false);
367 : :
3270 noah@leadboat.com 368 : 309417 : ReleaseSysCache(baseType);
369 : :
7656 tgl@sss.pgh.pa.us 370 : 309417 : return result;
371 : : }
5279 372 [ + + + + ]: 131498 : if (IsA(node, Param) &&
373 [ + + ]: 6946 : pstate != NULL && pstate->p_coerce_param_hook != NULL)
374 : : {
375 : : /*
376 : : * Allow the CoerceParamHook to decide what happens. It can return a
377 : : * transformed node (very possibly the same Param node), or return
378 : : * NULL to indicate we should proceed with normal coercion.
379 : : */
2411 peter_e@gmx.net 380 : 4303 : result = pstate->p_coerce_param_hook(pstate,
381 : : (Param *) node,
382 : : targetTypeId,
383 : : targetTypeMod,
384 : : location);
5279 tgl@sss.pgh.pa.us 385 [ + + ]: 4303 : if (result)
386 : 4287 : return result;
387 : : }
4783 388 [ + + ]: 127211 : if (IsA(node, CollateExpr))
389 : : {
390 : : /*
391 : : * If we have a COLLATE clause, we have to push the coercion
392 : : * underneath the COLLATE; or discard the COLLATE if the target type
393 : : * isn't collatable. This is really ugly, but there is little choice
394 : : * because the above hacks on Consts and Params wouldn't happen
395 : : * otherwise. This kluge has consequences in coerce_to_target_type.
396 : : */
4775 397 : 3405 : CollateExpr *coll = (CollateExpr *) node;
398 : :
1098 399 : 3405 : result = coerce_type(pstate, (Node *) coll->arg,
400 : : inputTypeId, targetTypeId, targetTypeMod,
401 : : ccontext, cformat, location);
402 [ + - ]: 3405 : if (type_is_collatable(targetTypeId))
403 : : {
404 : 3405 : CollateExpr *newcoll = makeNode(CollateExpr);
405 : :
406 : 3405 : newcoll->arg = (Expr *) result;
407 : 3405 : newcoll->collOid = coll->collOid;
408 : 3405 : newcoll->location = coll->location;
409 : 3405 : result = (Node *) newcoll;
410 : : }
411 : 3405 : return result;
412 : : }
6158 413 : 123806 : pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
414 : : &funcId);
415 [ + + ]: 123806 : if (pathtype != COERCION_PATH_NONE)
416 : : {
417 [ + + ]: 122159 : if (pathtype != COERCION_PATH_RELABELTYPE)
418 : : {
419 : : /*
420 : : * Generate an expression tree representing run-time application
421 : : * of the conversion function. If we are dealing with a domain
422 : : * target type, the conversion function will yield the base type,
423 : : * and we need to extract the correct typmod to use from the
424 : : * domain's typtypmod.
425 : : */
426 : : Oid baseTypeId;
427 : : int32 baseTypeMod;
428 : :
6584 429 : 42998 : baseTypeMod = targetTypeMod;
430 : 42998 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
431 : :
6158 432 : 42998 : result = build_coercion_expression(node, pathtype, funcId,
433 : : baseTypeId, baseTypeMod,
434 : : ccontext, cformat, location);
435 : :
436 : : /*
437 : : * If domain, coerce to the domain type and relabel with domain
438 : : * type ID, hiding the previous coercion node.
439 : : */
7896 440 [ + + ]: 42998 : if (targetTypeId != baseTypeId)
6584 441 : 1012 : result = coerce_to_domain(result, baseTypeId, baseTypeMod,
442 : : targetTypeId,
443 : : ccontext, cformat, location,
444 : : true);
445 : : }
446 : : else
447 : : {
448 : : /*
449 : : * We don't need to do a physical conversion, but we do need to
450 : : * attach a RelabelType node so that the expression will be seen
451 : : * to have the intended type when inspected by higher-level code.
452 : : *
453 : : * Also, domains may have value restrictions beyond the base type
454 : : * that must be accounted for. If the destination is a domain
455 : : * then we won't need a RelabelType node.
456 : : */
457 : 79161 : result = coerce_to_domain(node, InvalidOid, -1, targetTypeId,
458 : : ccontext, cformat, location,
459 : : false);
7741 460 [ + + ]: 79161 : if (result == node)
461 : : {
462 : : /*
463 : : * XXX could we label result with exprTypmod(node) instead of
464 : : * default -1 typmod, to save a possible length-coercion
465 : : * later? Would work if both types have same interpretation of
466 : : * typmod, which is likely but not certain.
467 : : */
5708 468 : 60882 : RelabelType *r = makeRelabelType((Expr *) result,
469 : : targetTypeId, -1,
470 : : InvalidOid,
471 : : cformat);
472 : :
473 : 60882 : r->location = location;
474 : 60882 : result = (Node *) r;
475 : : }
476 : : }
7656 477 : 122159 : return result;
478 : : }
7279 479 [ + + + - ]: 2582 : if (inputTypeId == RECORDOID &&
480 : 935 : ISCOMPLEX(targetTypeId))
481 : : {
482 : : /* Coerce a RECORD to a specific complex type */
483 : 935 : return coerce_record_to_complex(pstate, node, targetTypeId,
484 : : ccontext, cformat, location);
485 : : }
6919 486 [ + + + - ]: 1386 : if (targetTypeId == RECORDOID &&
487 : 674 : ISCOMPLEX(inputTypeId))
488 : : {
489 : : /* Coerce a specific complex type to RECORD */
490 : : /* NB: we do NOT want a RelabelType here */
491 : 674 : return node;
492 : : }
493 : : #ifdef NOT_USED
494 : : if (inputTypeId == RECORDARRAYOID &&
495 : : is_complex_array(targetTypeId))
496 : : {
497 : : /* Coerce record[] to a specific complex array type */
498 : : /* not implemented yet ... */
499 : : }
500 : : #endif
5662 501 [ + + + - ]: 46 : if (targetTypeId == RECORDARRAYOID &&
502 : 8 : is_complex_array(inputTypeId))
503 : : {
504 : : /* Coerce a specific complex array type to record[] */
505 : : /* NB: we do NOT want a RelabelType here */
506 : 8 : return node;
507 : : }
4852 peter_e@gmx.net 508 [ + + ]: 30 : if (typeInheritsFrom(inputTypeId, targetTypeId)
509 [ + - ]: 3 : || typeIsOfTypedTable(inputTypeId, targetTypeId))
510 : : {
511 : : /*
512 : : * Input class type is a subclass of target, so generate an
513 : : * appropriate runtime conversion (removing unneeded columns and
514 : : * possibly rearranging the ones that are wanted).
515 : : *
516 : : * We will also get here when the input is a domain over a subclass of
517 : : * the target type. To keep life simple for the executor, we define
518 : : * ConvertRowtypeExpr as only working between regular composite types;
519 : : * therefore, in such cases insert a RelabelType to smash the input
520 : : * expression down to its base type.
521 : : */
2362 tgl@sss.pgh.pa.us 522 : 30 : Oid baseTypeId = getBaseType(inputTypeId);
7064 523 : 30 : ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
524 : :
2362 525 [ - + ]: 30 : if (baseTypeId != inputTypeId)
526 : : {
2362 tgl@sss.pgh.pa.us 527 :UBC 0 : RelabelType *rt = makeRelabelType((Expr *) node,
528 : : baseTypeId, -1,
529 : : InvalidOid,
530 : : COERCE_IMPLICIT_CAST);
531 : :
532 : 0 : rt->location = location;
533 : 0 : node = (Node *) rt;
534 : : }
7064 tgl@sss.pgh.pa.us 535 :CBC 30 : r->arg = (Expr *) node;
536 : 30 : r->resulttype = targetTypeId;
537 : 30 : r->convertformat = cformat;
5708 538 : 30 : r->location = location;
7064 539 : 30 : return (Node *) r;
540 : : }
541 : : /* If we get here, caller blew it */
7575 tgl@sss.pgh.pa.us 542 [ # # ]:UBC 0 : elog(ERROR, "failed to find conversion function from %s to %s",
543 : : format_type_be(inputTypeId), format_type_be(targetTypeId));
544 : : return NULL; /* keep compiler quiet */
545 : : }
546 : :
547 : :
548 : : /*
549 : : * can_coerce_type()
550 : : * Can input_typeids be coerced to target_typeids?
551 : : *
552 : : * We must be told the context (CAST construct, assignment, implicit coercion)
553 : : * as this determines the set of available casts.
554 : : */
555 : : bool
2000 peter_e@gmx.net 556 :CBC 921000 : can_coerce_type(int nargs, const Oid *input_typeids, const Oid *target_typeids,
557 : : CoercionContext ccontext)
558 : : {
7677 tgl@sss.pgh.pa.us 559 : 921000 : bool have_generics = false;
560 : : int i;
561 : :
562 : : /* run through argument list... */
9472 lockhart@fourpalms.o 563 [ + + ]: 1632834 : for (i = 0; i < nargs; i++)
564 : : {
8768 bruce@momjian.us 565 : 1047765 : Oid inputTypeId = input_typeids[i];
7879 tgl@sss.pgh.pa.us 566 : 1047765 : Oid targetTypeId = target_typeids[i];
567 : : CoercionPathType pathtype;
568 : : Oid funcId;
569 : :
570 : : /* no problem if same type */
8795 571 [ + + ]: 1047765 : if (inputTypeId == targetTypeId)
572 : 711834 : continue;
573 : :
574 : : /* accept if target is ANY */
7906 575 [ + + ]: 810660 : if (targetTypeId == ANYOID)
576 : 4873 : continue;
577 : :
578 : : /* accept if target is polymorphic, for now */
6222 579 [ + + + + : 805787 : if (IsPolymorphicType(targetTypeId))
+ + + + +
+ + + + +
+ + + + +
+ + + ]
580 : : {
2489 581 : 89692 : have_generics = true; /* do more checking later */
7677 582 : 89692 : continue;
583 : : }
584 : :
585 : : /*
586 : : * If input is an untyped string constant, assume we can convert it to
587 : : * anything.
588 : : */
7424 589 [ + + ]: 716095 : if (inputTypeId == UNKNOWNOID)
590 : 271246 : continue;
591 : :
592 : : /*
593 : : * If pg_cast shows that we can coerce, accept. This test now covers
594 : : * both binary-compatible and coercion-function cases.
595 : : */
6158 596 : 444849 : pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
597 : : &funcId);
598 [ + + ]: 444849 : if (pathtype != COERCION_PATH_NONE)
7906 599 : 107422 : continue;
600 : :
601 : : /*
602 : : * If input is RECORD and target is a composite type, assume we can
603 : : * coerce (may need tighter checking here)
604 : : */
7279 605 [ + + + + ]: 338431 : if (inputTypeId == RECORDOID &&
606 : 1004 : ISCOMPLEX(targetTypeId))
607 : 935 : continue;
608 : :
609 : : /*
610 : : * If input is a composite type and target is RECORD, accept
611 : : */
6919 612 [ + + + + ]: 341974 : if (targetTypeId == RECORDOID &&
613 : 5482 : ISCOMPLEX(inputTypeId))
614 : 531 : continue;
615 : :
616 : : #ifdef NOT_USED /* not implemented yet */
617 : :
618 : : /*
619 : : * If input is record[] and target is a composite array type, assume
620 : : * we can coerce (may need tighter checking here)
621 : : */
622 : : if (inputTypeId == RECORDARRAYOID &&
623 : : is_complex_array(targetTypeId))
624 : : continue;
625 : : #endif
626 : :
627 : : /*
628 : : * If input is a composite array type and target is record[], accept
629 : : */
5662 630 [ + + - + ]: 335967 : if (targetTypeId == RECORDARRAYOID &&
631 : 6 : is_complex_array(inputTypeId))
5662 tgl@sss.pgh.pa.us 632 :UBC 0 : continue;
633 : :
634 : : /*
635 : : * If input is a class type that inherits from target, accept
636 : : */
4852 peter_e@gmx.net 637 [ + + ]:CBC 335961 : if (typeInheritsFrom(inputTypeId, targetTypeId)
638 [ + + ]: 335934 : || typeIsOfTypedTable(inputTypeId, targetTypeId))
8795 tgl@sss.pgh.pa.us 639 : 30 : continue;
640 : :
641 : : /*
642 : : * Else, cannot coerce at this argument position
643 : : */
7896 644 : 335931 : return false;
645 : : }
646 : :
647 : : /* If we found any generic argument types, cross-check them */
7677 648 [ + + ]: 585069 : if (have_generics)
649 : : {
650 [ + + ]: 60753 : if (!check_generic_type_consistency(input_typeids, target_typeids,
651 : : nargs))
652 : 35417 : return false;
653 : : }
654 : :
9472 lockhart@fourpalms.o 655 : 549652 : return true;
656 : : }
657 : :
658 : :
659 : : /*
660 : : * Create an expression tree to represent coercion to a domain type.
661 : : *
662 : : * 'arg': input expression
663 : : * 'baseTypeId': base type of domain, if known (pass InvalidOid if caller
664 : : * has not bothered to look this up)
665 : : * 'baseTypeMod': base type typmod of domain, if known (pass -1 if caller
666 : : * has not bothered to look this up)
667 : : * 'typeId': target type to coerce to
668 : : * 'ccontext': context indicator to control coercions
669 : : * 'cformat': coercion display format
670 : : * 'location': coercion request location
671 : : * 'hideInputCoercion': if true, hide the input coercion under this one.
672 : : *
673 : : * If the target type isn't a domain, the given 'arg' is returned as-is.
674 : : */
675 : : Node *
6584 tgl@sss.pgh.pa.us 676 : 102898 : coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
677 : : CoercionContext ccontext, CoercionForm cformat, int location,
678 : : bool hideInputCoercion)
679 : : {
680 : : CoerceToDomain *result;
681 : :
682 : : /* Get the base type if it hasn't been supplied */
7741 683 [ + + ]: 102898 : if (baseTypeId == InvalidOid)
6584 684 : 88437 : baseTypeId = getBaseTypeAndTypmod(typeId, &baseTypeMod);
685 : :
686 : : /* If it isn't a domain, return the node as it was passed in */
7741 687 [ + + ]: 102898 : if (baseTypeId == typeId)
688 : 70119 : return arg;
689 : :
690 : : /* Suppress display of nested coercion steps */
7242 691 [ + + ]: 32779 : if (hideInputCoercion)
692 : 1012 : hide_coercion_node(arg);
693 : :
694 : : /*
695 : : * If the domain applies a typmod to its base type, build the appropriate
696 : : * coercion step. Mark it implicit for display purposes, because we don't
697 : : * want it shown separately by ruleutils.c; but the isExplicit flag passed
698 : : * to the conversion function depends on the manner in which the domain
699 : : * coercion is invoked, so that the semantics of implicit and explicit
700 : : * coercion differ. (Is that really the behavior we want?)
701 : : *
702 : : * NOTE: because we apply this as part of the fixed expression structure,
703 : : * ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
704 : : * would be safe to do anyway, without lots of knowledge about what the
705 : : * base type thinks the typmod means.
706 : : */
2388 707 : 32779 : arg = coerce_type_typmod(arg, baseTypeId, baseTypeMod,
708 : : ccontext, COERCE_IMPLICIT_CAST, location,
709 : : false);
710 : :
711 : : /*
712 : : * Now build the domain coercion node. This represents run-time checking
713 : : * of any constraints currently attached to the domain. This also ensures
714 : : * that the expression is properly labeled as to result type.
715 : : */
7741 716 : 32779 : result = makeNode(CoerceToDomain);
717 : 32779 : result->arg = (Expr *) arg;
718 : 32779 : result->resulttype = typeId;
719 : 32779 : result->resulttypmod = -1; /* currently, always -1 for domains */
720 : : /* resultcollid will be set by parse_collate.c */
721 : 32779 : result->coercionformat = cformat;
5708 722 : 32779 : result->location = location;
723 : :
7741 724 : 32779 : return (Node *) result;
725 : : }
726 : :
727 : :
728 : : /*
729 : : * coerce_type_typmod()
730 : : * Force a value to a particular typmod, if meaningful and possible.
731 : : *
732 : : * This is applied to values that are going to be stored in a relation
733 : : * (where we have an atttypmod for the column) as well as values being
734 : : * explicitly CASTed (where the typmod comes from the target type spec).
735 : : *
736 : : * The caller must have already ensured that the value is of the correct
737 : : * type, typically by applying coerce_type.
738 : : *
739 : : * ccontext may affect semantics, depending on whether the length coercion
740 : : * function pays attention to the isExplicit flag it's passed.
741 : : *
742 : : * cformat determines the display properties of the generated node (if any).
743 : : *
744 : : * If hideInputCoercion is true *and* we generate a node, the input node is
745 : : * forced to IMPLICIT display form, so that only the typmod coercion node will
746 : : * be visible when displaying the expression.
747 : : *
748 : : * NOTE: this does not need to work on domain types, because any typmod
749 : : * coercion for a domain is considered to be part of the type coercion
750 : : * needed to produce the domain value in the first place. So, no getBaseType.
751 : : */
752 : : static Node *
7879 753 : 384928 : coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
754 : : CoercionContext ccontext, CoercionForm cformat,
755 : : int location,
756 : : bool hideInputCoercion)
757 : : {
758 : : CoercionPathType pathtype;
759 : : Oid funcId;
760 : :
761 : : /* Skip coercion if already done */
982 762 [ + + ]: 384928 : if (targetTypMod == exprTypmod(node))
8854 763 : 374880 : return node;
764 : :
765 : : /* Suppress display of nested coercion steps */
982 766 [ + + ]: 10048 : if (hideInputCoercion)
767 : 552 : hide_coercion_node(node);
768 : :
769 : : /*
770 : : * A negative typmod means that no actual coercion is needed, but we still
771 : : * want a RelabelType to ensure that the expression exposes the intended
772 : : * typmod.
773 : : */
850 774 [ + + ]: 10048 : if (targetTypMod < 0)
775 : 15 : pathtype = COERCION_PATH_NONE;
776 : : else
777 : 10033 : pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
778 : :
6158 779 [ + + ]: 10048 : if (pathtype != COERCION_PATH_NONE)
780 : : {
781 : 10027 : node = build_coercion_expression(node, pathtype, funcId,
782 : : targetTypeId, targetTypMod,
783 : : ccontext, cformat, location);
784 : : }
785 : : else
786 : : {
787 : : /*
788 : : * We don't need to perform any actual coercion step, but we should
789 : : * apply a RelabelType to ensure that the expression exposes the
790 : : * intended typmod.
791 : : */
982 792 : 21 : node = applyRelabelType(node, targetTypeId, targetTypMod,
793 : : exprCollation(node),
794 : : cformat, location, false);
795 : : }
796 : :
7242 797 : 10048 : return node;
798 : : }
799 : :
800 : : /*
801 : : * Mark a coercion node as IMPLICIT so it will never be displayed by
802 : : * ruleutils.c. We use this when we generate a nest of coercion nodes
803 : : * to implement what is logically one conversion; the inner nodes are
804 : : * forced to IMPLICIT_CAST format. This does not change their semantics,
805 : : * only display behavior.
806 : : *
807 : : * It is caller error to call this on something that doesn't have a
808 : : * CoercionForm field.
809 : : */
810 : : static void
811 : 1564 : hide_coercion_node(Node *node)
812 : : {
813 [ + + ]: 1564 : if (IsA(node, FuncExpr))
814 : 708 : ((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
815 [ + + ]: 856 : else if (IsA(node, RelabelType))
816 : 162 : ((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
6158 817 [ + + ]: 694 : else if (IsA(node, CoerceViaIO))
818 : 688 : ((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
6228 819 [ + - ]: 6 : else if (IsA(node, ArrayCoerceExpr))
820 : 6 : ((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
7064 tgl@sss.pgh.pa.us 821 [ # # ]:UBC 0 : else if (IsA(node, ConvertRowtypeExpr))
822 : 0 : ((ConvertRowtypeExpr *) node)->convertformat = COERCE_IMPLICIT_CAST;
7242 823 [ # # ]: 0 : else if (IsA(node, RowExpr))
824 : 0 : ((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
825 [ # # ]: 0 : else if (IsA(node, CoerceToDomain))
826 : 0 : ((CoerceToDomain *) node)->coercionformat = COERCE_IMPLICIT_CAST;
827 : : else
828 [ # # ]: 0 : elog(ERROR, "unsupported node type: %d", (int) nodeTag(node));
7242 tgl@sss.pgh.pa.us 829 :CBC 1564 : }
830 : :
831 : : /*
832 : : * build_coercion_expression()
833 : : * Construct an expression tree for applying a pg_cast entry.
834 : : *
835 : : * This is used for both type-coercion and length-coercion operations,
836 : : * since there is no difference in terms of the calling convention.
837 : : */
838 : : static Node *
6228 839 : 53025 : build_coercion_expression(Node *node,
840 : : CoercionPathType pathtype,
841 : : Oid funcId,
842 : : Oid targetTypeId, int32 targetTypMod,
843 : : CoercionContext ccontext, CoercionForm cformat,
844 : : int location)
845 : : {
846 : 53025 : int nargs = 0;
847 : :
848 [ + + ]: 53025 : if (OidIsValid(funcId))
849 : : {
850 : : HeapTuple tp;
851 : : Form_pg_proc procstruct;
852 : :
5173 rhaas@postgresql.org 853 : 40238 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
6228 tgl@sss.pgh.pa.us 854 [ - + ]: 40238 : if (!HeapTupleIsValid(tp))
6228 tgl@sss.pgh.pa.us 855 [ # # ]:UBC 0 : elog(ERROR, "cache lookup failed for function %u", funcId);
6228 tgl@sss.pgh.pa.us 856 :CBC 40238 : procstruct = (Form_pg_proc) GETSTRUCT(tp);
857 : :
858 : : /*
859 : : * These Asserts essentially check that function is a legal coercion
860 : : * function. We can't make the seemingly obvious tests on prorettype
861 : : * and proargtypes[0], even in the COERCION_PATH_FUNC case, because of
862 : : * various binary-compatibility cases.
863 : : */
864 : : /* Assert(targetTypeId == procstruct->prorettype); */
865 [ - + ]: 40238 : Assert(!procstruct->proretset);
2235 peter_e@gmx.net 866 [ - + ]: 40238 : Assert(procstruct->prokind == PROKIND_FUNCTION);
6228 tgl@sss.pgh.pa.us 867 : 40238 : nargs = procstruct->pronargs;
868 [ + - - + ]: 40238 : Assert(nargs >= 1 && nargs <= 3);
869 : : /* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
870 [ + + - + ]: 40238 : Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
871 [ + + - + ]: 40238 : Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
872 : :
873 : 40238 : ReleaseSysCache(tp);
874 : : }
875 : :
6158 876 [ + + ]: 53025 : if (pathtype == COERCION_PATH_FUNC)
877 : : {
878 : : /* We build an ordinary FuncExpr with special arguments */
879 : : FuncExpr *fexpr;
880 : : List *args;
881 : : Const *cons;
882 : :
6228 883 [ - + ]: 40196 : Assert(OidIsValid(funcId));
884 : :
885 : 40196 : args = list_make1(node);
886 : :
887 [ + + ]: 40196 : if (nargs >= 2)
888 : : {
889 : : /* Pass target typmod as an int4 constant */
890 : 10618 : cons = makeConst(INT4OID,
891 : : -1,
892 : : InvalidOid,
893 : : sizeof(int32),
894 : : Int32GetDatum(targetTypMod),
895 : : false,
896 : : true);
897 : :
898 : 10618 : args = lappend(args, cons);
899 : : }
900 : :
901 [ + + ]: 40196 : if (nargs == 3)
902 : : {
903 : : /* Pass it a boolean isExplicit parameter, too */
904 : 6771 : cons = makeConst(BOOLOID,
905 : : -1,
906 : : InvalidOid,
907 : : sizeof(bool),
908 : : BoolGetDatum(ccontext == COERCION_EXPLICIT),
909 : : false,
910 : : true);
911 : :
912 : 6771 : args = lappend(args, cons);
913 : : }
914 : :
4775 915 : 40196 : fexpr = makeFuncExpr(funcId, targetTypeId, args,
916 : : InvalidOid, InvalidOid, cformat);
5708 917 : 40196 : fexpr->location = location;
918 : 40196 : return (Node *) fexpr;
919 : : }
6158 920 [ + + ]: 12829 : else if (pathtype == COERCION_PATH_ARRAYCOERCE)
921 : : {
922 : : /* We need to build an ArrayCoerceExpr */
923 : 2449 : ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
2388 924 : 2449 : CaseTestExpr *ctest = makeNode(CaseTestExpr);
925 : : Oid sourceBaseTypeId;
926 : : int32 sourceBaseTypeMod;
927 : : Oid targetElementType;
928 : : Node *elemexpr;
929 : :
930 : : /*
931 : : * Look through any domain over the source array type. Note we don't
932 : : * expect that the target type is a domain; it must be a plain array.
933 : : * (To get to a domain target type, we'll do coerce_to_domain later.)
934 : : */
935 : 2449 : sourceBaseTypeMod = exprTypmod(node);
936 : 2449 : sourceBaseTypeId = getBaseTypeAndTypmod(exprType(node),
937 : : &sourceBaseTypeMod);
938 : :
939 : : /*
940 : : * Set up a CaseTestExpr representing one element of the source array.
941 : : * This is an abuse of CaseTestExpr, but it's OK as long as there
942 : : * can't be any CaseExpr or ArrayCoerceExpr within the completed
943 : : * elemexpr.
944 : : */
945 : 2449 : ctest->typeId = get_element_type(sourceBaseTypeId);
946 [ - + ]: 2449 : Assert(OidIsValid(ctest->typeId));
947 : 2449 : ctest->typeMod = sourceBaseTypeMod;
948 : 2449 : ctest->collation = InvalidOid; /* Assume coercions don't care */
949 : :
950 : : /* And coerce it to the target element type */
951 : 2449 : targetElementType = get_element_type(targetTypeId);
952 [ - + ]: 2449 : Assert(OidIsValid(targetElementType));
953 : :
954 : 2449 : elemexpr = coerce_to_target_type(NULL,
955 : : (Node *) ctest,
956 : : ctest->typeId,
957 : : targetElementType,
958 : : targetTypMod,
959 : : ccontext,
960 : : cformat,
961 : : location);
962 [ - + ]: 2449 : if (elemexpr == NULL) /* shouldn't happen */
2388 tgl@sss.pgh.pa.us 963 [ # # ]:UBC 0 : elog(ERROR, "failed to coerce array element type as expected");
964 : :
6158 tgl@sss.pgh.pa.us 965 :CBC 2449 : acoerce->arg = (Expr *) node;
2388 966 : 2449 : acoerce->elemexpr = (Expr *) elemexpr;
6158 967 : 2449 : acoerce->resulttype = targetTypeId;
968 : :
969 : : /*
970 : : * Label the output as having a particular element typmod only if we
971 : : * ended up with a per-element expression that is labeled that way.
972 : : */
2388 973 : 2449 : acoerce->resulttypmod = exprTypmod(elemexpr);
974 : : /* resultcollid will be set by parse_collate.c */
6158 975 : 2449 : acoerce->coerceformat = cformat;
5708 976 : 2449 : acoerce->location = location;
977 : :
6158 978 : 2449 : return (Node *) acoerce;
979 : : }
980 [ + - ]: 10380 : else if (pathtype == COERCION_PATH_COERCEVIAIO)
981 : : {
982 : : /* We need to build a CoerceViaIO node */
983 : 10380 : CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
984 : :
985 [ - + ]: 10380 : Assert(!OidIsValid(funcId));
986 : :
987 : 10380 : iocoerce->arg = (Expr *) node;
988 : 10380 : iocoerce->resulttype = targetTypeId;
989 : : /* resultcollid will be set by parse_collate.c */
990 : 10380 : iocoerce->coerceformat = cformat;
5708 991 : 10380 : iocoerce->location = location;
992 : :
6158 993 : 10380 : return (Node *) iocoerce;
994 : : }
995 : : else
996 : : {
6158 tgl@sss.pgh.pa.us 997 [ # # ]:UBC 0 : elog(ERROR, "unsupported pathtype %d in build_coercion_expression",
998 : : (int) pathtype);
999 : : return NULL; /* keep compiler quiet */
1000 : : }
1001 : : }
1002 : :
1003 : :
1004 : : /*
1005 : : * coerce_record_to_complex
1006 : : * Coerce a RECORD to a specific composite type.
1007 : : *
1008 : : * Currently we only support this for inputs that are RowExprs or whole-row
1009 : : * Vars.
1010 : : */
1011 : : static Node *
7279 tgl@sss.pgh.pa.us 1012 :CBC 935 : coerce_record_to_complex(ParseState *pstate, Node *node,
1013 : : Oid targetTypeId,
1014 : : CoercionContext ccontext,
1015 : : CoercionForm cformat,
1016 : : int location)
1017 : : {
1018 : : RowExpr *rowexpr;
1019 : : Oid baseTypeId;
2362 1020 : 935 : int32 baseTypeMod = -1;
1021 : : TupleDesc tupdesc;
7279 1022 : 935 : List *args = NIL;
1023 : : List *newargs;
1024 : : int i;
1025 : : int ucolno;
1026 : : ListCell *arg;
1027 : :
1028 [ + - + - ]: 935 : if (node && IsA(node, RowExpr))
1029 : : {
1030 : : /*
1031 : : * Since the RowExpr must be of type RECORD, we needn't worry about it
1032 : : * containing any dropped columns.
1033 : : */
1034 : 935 : args = ((RowExpr *) node)->args;
1035 : : }
7279 tgl@sss.pgh.pa.us 1036 [ # # # # ]:UBC 0 : else if (node && IsA(node, Var) &&
1037 [ # # ]: 0 : ((Var *) node)->varattno == InvalidAttrNumber)
1038 : 0 : {
7168 bruce@momjian.us 1039 : 0 : int rtindex = ((Var *) node)->varno;
1040 : 0 : int sublevels_up = ((Var *) node)->varlevelsup;
5704 tgl@sss.pgh.pa.us 1041 : 0 : int vlocation = ((Var *) node)->location;
1042 : : ParseNamespaceItem *nsitem;
1043 : :
1564 1044 : 0 : nsitem = GetNSItemByRangeTablePosn(pstate, rtindex, sublevels_up);
440 1045 : 0 : args = expandNSItemVars(pstate, nsitem, sublevels_up, vlocation, NULL);
1046 : : }
1047 : : else
7279 1048 [ # # ]: 0 : ereport(ERROR,
1049 : : (errcode(ERRCODE_CANNOT_COERCE),
1050 : : errmsg("cannot cast type %s to %s",
1051 : : format_type_be(RECORDOID),
1052 : : format_type_be(targetTypeId)),
1053 : : parser_coercion_errposition(pstate, location, node)));
1054 : :
1055 : : /*
1056 : : * Look up the composite type, accounting for possibility that what we are
1057 : : * given is a domain over composite.
1058 : : */
2362 tgl@sss.pgh.pa.us 1059 :CBC 935 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
1060 : 935 : tupdesc = lookup_rowtype_tupdesc(baseTypeId, baseTypeMod);
1061 : :
1062 : : /* Process the fields */
7279 1063 : 935 : newargs = NIL;
7180 1064 : 935 : ucolno = 1;
1065 : 935 : arg = list_head(args);
1066 [ + + ]: 3072 : for (i = 0; i < tupdesc->natts; i++)
1067 : : {
1068 : : Node *expr;
1069 : : Node *cexpr;
1070 : : Oid exprtype;
2429 andres@anarazel.de 1071 : 2137 : Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1072 : :
1073 : : /* Fill in NULLs for dropped columns in rowtype */
1074 [ + + ]: 2137 : if (attr->attisdropped)
1075 : : {
1076 : : /*
1077 : : * can't use atttypid here, but it doesn't really matter what type
1078 : : * the Const claims to be.
1079 : : */
4769 tgl@sss.pgh.pa.us 1080 : 3 : newargs = lappend(newargs,
1081 : 3 : makeNullConst(INT4OID, -1, InvalidOid));
7180 1082 : 3 : continue;
1083 : : }
1084 : :
1085 [ - + ]: 2134 : if (arg == NULL)
7180 tgl@sss.pgh.pa.us 1086 [ # # ]:UBC 0 : ereport(ERROR,
1087 : : (errcode(ERRCODE_CANNOT_COERCE),
1088 : : errmsg("cannot cast type %s to %s",
1089 : : format_type_be(RECORDOID),
1090 : : format_type_be(targetTypeId)),
1091 : : errdetail("Input has too few columns."),
1092 : : parser_coercion_errposition(pstate, location, node)));
7180 tgl@sss.pgh.pa.us 1093 :CBC 2134 : expr = (Node *) lfirst(arg);
1094 : 2134 : exprtype = exprType(expr);
1095 : :
5708 1096 : 2134 : cexpr = coerce_to_target_type(pstate,
1097 : : expr, exprtype,
1098 : : attr->atttypid,
1099 : : attr->atttypmod,
1100 : : ccontext,
1101 : : COERCE_IMPLICIT_CAST,
1102 : : -1);
1103 [ - + ]: 2134 : if (cexpr == NULL)
7279 tgl@sss.pgh.pa.us 1104 [ # # ]:UBC 0 : ereport(ERROR,
1105 : : (errcode(ERRCODE_CANNOT_COERCE),
1106 : : errmsg("cannot cast type %s to %s",
1107 : : format_type_be(RECORDOID),
1108 : : format_type_be(targetTypeId)),
1109 : : errdetail("Cannot cast type %s to %s in column %d.",
1110 : : format_type_be(exprtype),
1111 : : format_type_be(attr->atttypid),
1112 : : ucolno),
1113 : : parser_coercion_errposition(pstate, location, expr)));
5708 tgl@sss.pgh.pa.us 1114 :CBC 2134 : newargs = lappend(newargs, cexpr);
7180 1115 : 2134 : ucolno++;
1735 1116 : 2134 : arg = lnext(args, arg);
1117 : : }
7180 1118 [ - + ]: 935 : if (arg != NULL)
7180 tgl@sss.pgh.pa.us 1119 [ # # ]:UBC 0 : ereport(ERROR,
1120 : : (errcode(ERRCODE_CANNOT_COERCE),
1121 : : errmsg("cannot cast type %s to %s",
1122 : : format_type_be(RECORDOID),
1123 : : format_type_be(targetTypeId)),
1124 : : errdetail("Input has too many columns."),
1125 : : parser_coercion_errposition(pstate, location, node)));
1126 : :
6512 tgl@sss.pgh.pa.us 1127 [ + - ]:CBC 935 : ReleaseTupleDesc(tupdesc);
1128 : :
7279 1129 : 935 : rowexpr = makeNode(RowExpr);
1130 : 935 : rowexpr->args = newargs;
2362 1131 : 935 : rowexpr->row_typeid = baseTypeId;
7279 1132 : 935 : rowexpr->row_format = cformat;
5669 1133 : 935 : rowexpr->colnames = NIL; /* not needed for named target type */
5708 1134 : 935 : rowexpr->location = location;
1135 : :
1136 : : /* If target is a domain, apply constraints */
2362 1137 [ + + ]: 935 : if (baseTypeId != targetTypeId)
1138 : : {
1139 : 77 : rowexpr->row_format = COERCE_IMPLICIT_CAST;
1140 : 77 : return coerce_to_domain((Node *) rowexpr,
1141 : : baseTypeId, baseTypeMod,
1142 : : targetTypeId,
1143 : : ccontext, cformat, location,
1144 : : false);
1145 : : }
1146 : :
7279 1147 : 858 : return (Node *) rowexpr;
1148 : : }
1149 : :
1150 : : /*
1151 : : * coerce_to_boolean()
1152 : : * Coerce an argument of a construct that requires boolean input
1153 : : * (AND, OR, NOT, etc). Also check that input is not a set.
1154 : : *
1155 : : * Returns the possibly-transformed node tree.
1156 : : *
1157 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1158 : : * processing is wanted.
1159 : : */
1160 : : Node *
7656 1161 : 358236 : coerce_to_boolean(ParseState *pstate, Node *node,
1162 : : const char *constructName)
1163 : : {
8008 1164 : 358236 : Oid inputTypeId = exprType(node);
1165 : :
1166 [ + + ]: 358236 : if (inputTypeId != BOOLOID)
1167 : : {
1168 : : Node *newnode;
1169 : :
5708 1170 : 36 : newnode = coerce_to_target_type(pstate, node, inputTypeId,
1171 : : BOOLOID, -1,
1172 : : COERCION_ASSIGNMENT,
1173 : : COERCE_IMPLICIT_CAST,
1174 : : -1);
1175 [ + + ]: 36 : if (newnode == NULL)
7575 1176 [ + - ]: 3 : ereport(ERROR,
1177 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1178 : : /* translator: first %s is name of a SQL construct, eg WHERE */
1179 : : errmsg("argument of %s must be type %s, not type %s",
1180 : : constructName, "boolean",
1181 : : format_type_be(inputTypeId)),
1182 : : parser_errposition(pstate, exprLocation(node))));
5708 1183 : 33 : node = newnode;
1184 : : }
1185 : :
8008 1186 [ - + ]: 358233 : if (expression_returns_set(node))
7575 tgl@sss.pgh.pa.us 1187 [ # # ]:UBC 0 : ereport(ERROR,
1188 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1189 : : /* translator: %s is name of a SQL construct, eg WHERE */
1190 : : errmsg("argument of %s must not return a set",
1191 : : constructName),
1192 : : parser_errposition(pstate, exprLocation(node))));
1193 : :
7591 tgl@sss.pgh.pa.us 1194 :CBC 358233 : return node;
1195 : : }
1196 : :
1197 : : /*
1198 : : * coerce_to_specific_type_typmod()
1199 : : * Coerce an argument of a construct that requires a specific data type,
1200 : : * with a specific typmod. Also check that input is not a set.
1201 : : *
1202 : : * Returns the possibly-transformed node tree.
1203 : : *
1204 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1205 : : * processing is wanted.
1206 : : */
1207 : : Node *
2594 alvherre@alvh.no-ip. 1208 : 7252 : coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
1209 : : Oid targetTypeId, int32 targetTypmod,
1210 : : const char *constructName)
1211 : : {
6324 peter_e@gmx.net 1212 : 7252 : Oid inputTypeId = exprType(node);
1213 : :
6321 tgl@sss.pgh.pa.us 1214 [ + + ]: 7252 : if (inputTypeId != targetTypeId)
1215 : : {
1216 : : Node *newnode;
1217 : :
5708 1218 : 5159 : newnode = coerce_to_target_type(pstate, node, inputTypeId,
1219 : : targetTypeId, targetTypmod,
1220 : : COERCION_ASSIGNMENT,
1221 : : COERCE_IMPLICIT_CAST,
1222 : : -1);
1223 [ + + ]: 5153 : if (newnode == NULL)
6324 peter_e@gmx.net 1224 [ + - ]: 3 : ereport(ERROR,
1225 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1226 : : /* translator: first %s is name of a SQL construct, eg LIMIT */
1227 : : errmsg("argument of %s must be type %s, not type %s",
1228 : : constructName,
1229 : : format_type_be(targetTypeId),
1230 : : format_type_be(inputTypeId)),
1231 : : parser_errposition(pstate, exprLocation(node))));
5708 tgl@sss.pgh.pa.us 1232 : 5150 : node = newnode;
1233 : : }
1234 : :
6324 peter_e@gmx.net 1235 [ - + ]: 7243 : if (expression_returns_set(node))
6324 peter_e@gmx.net 1236 [ # # ]:UBC 0 : ereport(ERROR,
1237 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1238 : : /* translator: %s is name of a SQL construct, eg LIMIT */
1239 : : errmsg("argument of %s must not return a set",
1240 : : constructName),
1241 : : parser_errposition(pstate, exprLocation(node))));
1242 : :
6324 peter_e@gmx.net 1243 :CBC 7243 : return node;
1244 : : }
1245 : :
1246 : : /*
1247 : : * coerce_to_specific_type()
1248 : : * Coerce an argument of a construct that requires a specific data type.
1249 : : * Also check that input is not a set.
1250 : : *
1251 : : * Returns the possibly-transformed node tree.
1252 : : *
1253 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1254 : : * processing is wanted.
1255 : : */
1256 : : Node *
2594 alvherre@alvh.no-ip. 1257 : 7224 : coerce_to_specific_type(ParseState *pstate, Node *node,
1258 : : Oid targetTypeId,
1259 : : const char *constructName)
1260 : : {
1261 : 7224 : return coerce_to_specific_type_typmod(pstate, node,
1262 : : targetTypeId, -1,
1263 : : constructName);
1264 : : }
1265 : :
1266 : : /*
1267 : : * parser_coercion_errposition - report coercion error location, if possible
1268 : : *
1269 : : * We prefer to point at the coercion request (CAST, ::, etc) if possible;
1270 : : * but there may be no such location in the case of an implicit coercion.
1271 : : * In that case point at the input expression.
1272 : : *
1273 : : * XXX possibly this is more generally useful than coercion errors;
1274 : : * if so, should rename and place with parser_errposition.
1275 : : */
1276 : : int
5708 tgl@sss.pgh.pa.us 1277 : 26 : parser_coercion_errposition(ParseState *pstate,
1278 : : int coerce_location,
1279 : : Node *input_expr)
1280 : : {
1281 [ + - ]: 26 : if (coerce_location >= 0)
1481 1282 : 26 : return parser_errposition(pstate, coerce_location);
1283 : : else
1481 tgl@sss.pgh.pa.us 1284 :UBC 0 : return parser_errposition(pstate, exprLocation(input_expr));
1285 : : }
1286 : :
1287 : :
1288 : : /*
1289 : : * select_common_type()
1290 : : * Determine the common supertype of a list of input expressions.
1291 : : * This is used for determining the output type of CASE, UNION,
1292 : : * and similar constructs.
1293 : : *
1294 : : * 'exprs' is a *nonempty* list of expressions. Note that earlier items
1295 : : * in the list will be preferred if there is doubt.
1296 : : * 'context' is a phrase to use in the error message if we fail to select
1297 : : * a usable type. Pass NULL to have the routine return InvalidOid
1298 : : * rather than throwing an error on failure.
1299 : : * 'which_expr': if not NULL, receives a pointer to the particular input
1300 : : * expression from which the result type was taken.
1301 : : *
1302 : : * Caution: "failure" just means that there were inputs of different type
1303 : : * categories. It is not guaranteed that all the inputs are coercible to the
1304 : : * selected type; caller must check that (see verify_common_type).
1305 : : */
1306 : : Oid
5708 tgl@sss.pgh.pa.us 1307 :CBC 66941 : select_common_type(ParseState *pstate, List *exprs, const char *context,
1308 : : Node **which_expr)
1309 : : {
1310 : : Node *pexpr;
1311 : : Oid ptype;
1312 : : TYPCATEGORY pcategory;
1313 : : bool pispreferred;
1314 : : ListCell *lc;
1315 : :
1316 [ - + ]: 66941 : Assert(exprs != NIL);
1317 : 66941 : pexpr = (Node *) linitial(exprs);
1735 1318 : 66941 : lc = list_second_cell(exprs);
5708 1319 : 66941 : ptype = exprType(pexpr);
1320 : :
1321 : : /*
1322 : : * If all input types are valid and exactly the same, just pick that type.
1323 : : * This is the only way that we will resolve the result as being a domain
1324 : : * type; otherwise domains are smashed to their base types for comparison.
1325 : : */
5984 1326 [ + + ]: 66941 : if (ptype != UNKNOWNOID)
1327 : : {
1735 1328 [ + - + + : 104544 : for_each_cell(lc, exprs, lc)
+ + ]
1329 : : {
5421 bruce@momjian.us 1330 : 67952 : Node *nexpr = (Node *) lfirst(lc);
1331 : 67952 : Oid ntype = exprType(nexpr);
1332 : :
5984 tgl@sss.pgh.pa.us 1333 [ + + ]: 67952 : if (ntype != ptype)
1334 : 16938 : break;
1335 : : }
5708 1336 [ + + ]: 53530 : if (lc == NULL) /* got to the end of the list? */
1337 : : {
1338 [ + + ]: 36592 : if (which_expr)
1339 : 16786 : *which_expr = pexpr;
5984 1340 : 36592 : return ptype;
1341 : : }
1342 : : }
1343 : :
1344 : : /*
1345 : : * Nope, so set up for the full algorithm. Note that at this point, lc
1346 : : * points to the first list item with type different from pexpr's; we need
1347 : : * not re-examine any items the previous loop advanced over.
1348 : : */
1349 : 30349 : ptype = getBaseType(ptype);
5737 1350 : 30349 : get_type_category_preferred(ptype, &pcategory, &pispreferred);
1351 : :
1735 1352 [ + - + + : 89022 : for_each_cell(lc, exprs, lc)
+ + ]
1353 : : {
5708 1354 : 58679 : Node *nexpr = (Node *) lfirst(lc);
1355 : 58679 : Oid ntype = getBaseType(exprType(nexpr));
1356 : :
1357 : : /* move on to next one if no new information... */
5984 1358 [ + + + + ]: 58679 : if (ntype != UNKNOWNOID && ntype != ptype)
1359 : : {
1360 : : TYPCATEGORY ncategory;
1361 : : bool nispreferred;
1362 : :
5737 1363 : 10943 : get_type_category_preferred(ntype, &ncategory, &nispreferred);
5984 1364 [ + + ]: 10943 : if (ptype == UNKNOWNOID)
1365 : : {
1366 : : /* so far, only unknowns so take anything... */
5708 1367 : 7582 : pexpr = nexpr;
8592 1368 : 7582 : ptype = ntype;
5737 1369 : 7582 : pcategory = ncategory;
1370 : 7582 : pispreferred = nispreferred;
1371 : : }
1372 [ + + ]: 3361 : else if (ncategory != pcategory)
1373 : : {
1374 : : /*
1375 : : * both types in different categories? then not much hope...
1376 : : */
5650 1377 [ - + ]: 6 : if (context == NULL)
5650 tgl@sss.pgh.pa.us 1378 :UBC 0 : return InvalidOid;
7575 tgl@sss.pgh.pa.us 1379 [ + - ]:CBC 6 : ereport(ERROR,
1380 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1381 : : /*------
1382 : : translator: first %s is name of a SQL construct, eg CASE */
1383 : : errmsg("%s types %s and %s cannot be matched",
1384 : : context,
1385 : : format_type_be(ptype),
1386 : : format_type_be(ntype)),
1387 : : parser_errposition(pstate, exprLocation(nexpr))));
1388 : : }
5737 1389 [ + + + + ]: 4435 : else if (!pispreferred &&
6756 bruce@momjian.us 1390 : 1080 : can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
1391 [ + + ]: 684 : !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
1392 : : {
1393 : : /*
1394 : : * take new type if can coerce to it implicitly but not the
1395 : : * other way; but if we have a preferred type, stay on it.
1396 : : */
5708 tgl@sss.pgh.pa.us 1397 : 599 : pexpr = nexpr;
8592 1398 : 599 : ptype = ntype;
5737 1399 : 599 : pcategory = ncategory;
1400 : 599 : pispreferred = nispreferred;
1401 : : }
1402 : : }
1403 : : }
1404 : :
1405 : : /*
1406 : : * If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
1407 : : * then resolve as type TEXT. This situation comes up with constructs
1408 : : * like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
1409 : : * UNION SELECT 'bar'; It might seem desirable to leave the construct's
1410 : : * output type as UNKNOWN, but that really doesn't work, because we'd
1411 : : * probably end up needing a runtime coercion from UNKNOWN to something
1412 : : * else, and we usually won't have it. We need to coerce the unknown
1413 : : * literals while they are still literals, so a decision has to be made
1414 : : * now.
1415 : : */
8557 1416 [ + + ]: 30343 : if (ptype == UNKNOWNOID)
1417 : 5829 : ptype = TEXTOID;
1418 : :
5708 1419 [ + + ]: 30343 : if (which_expr)
1420 : 6543 : *which_expr = pexpr;
8592 1421 : 30343 : return ptype;
1422 : : }
1423 : :
1424 : : /*
1425 : : * select_common_type_from_oids()
1426 : : * Determine the common supertype of an array of type OIDs.
1427 : : *
1428 : : * This is the same logic as select_common_type(), but working from
1429 : : * an array of type OIDs not a list of expressions. As in that function,
1430 : : * earlier entries in the array have some preference over later ones.
1431 : : * On failure, return InvalidOid if noerror is true, else throw an error.
1432 : : *
1433 : : * Caution: "failure" just means that there were inputs of different type
1434 : : * categories. It is not guaranteed that all the inputs are coercible to the
1435 : : * selected type; caller must check that (see verify_common_type_from_oids).
1436 : : *
1437 : : * Note: neither caller will pass any UNKNOWNOID entries, so the tests
1438 : : * for that in this function are dead code. However, they don't cost much,
1439 : : * and it seems better to keep this logic as close to select_common_type()
1440 : : * as possible.
1441 : : */
1442 : : static Oid
1487 1443 : 3442 : select_common_type_from_oids(int nargs, const Oid *typeids, bool noerror)
1444 : : {
1445 : : Oid ptype;
1446 : : TYPCATEGORY pcategory;
1447 : : bool pispreferred;
1448 : 3442 : int i = 1;
1449 : :
1450 [ - + ]: 3442 : Assert(nargs > 0);
1451 : 3442 : ptype = typeids[0];
1452 : :
1453 : : /* If all input types are valid and exactly the same, pick that type. */
1454 [ + - ]: 3442 : if (ptype != UNKNOWNOID)
1455 : : {
1456 [ + + ]: 5094 : for (; i < nargs; i++)
1457 : : {
1458 [ + + ]: 2187 : if (typeids[i] != ptype)
1459 : 535 : break;
1460 : : }
1461 [ + + ]: 3442 : if (i == nargs)
1462 : 2907 : return ptype;
1463 : : }
1464 : :
1465 : : /*
1466 : : * Nope, so set up for the full algorithm. Note that at this point, we
1467 : : * can skip array entries before "i"; they are all equal to ptype.
1468 : : */
1469 : 535 : ptype = getBaseType(ptype);
1470 : 535 : get_type_category_preferred(ptype, &pcategory, &pispreferred);
1471 : :
1472 [ + + ]: 787 : for (; i < nargs; i++)
1473 : : {
1474 : 562 : Oid ntype = getBaseType(typeids[i]);
1475 : :
1476 : : /* move on to next one if no new information... */
1477 [ + - + + ]: 562 : if (ntype != UNKNOWNOID && ntype != ptype)
1478 : : {
1479 : : TYPCATEGORY ncategory;
1480 : : bool nispreferred;
1481 : :
1482 : 556 : get_type_category_preferred(ntype, &ncategory, &nispreferred);
1483 [ - + ]: 556 : if (ptype == UNKNOWNOID)
1484 : : {
1485 : : /* so far, only unknowns so take anything... */
1487 tgl@sss.pgh.pa.us 1486 :UBC 0 : ptype = ntype;
1487 : 0 : pcategory = ncategory;
1488 : 0 : pispreferred = nispreferred;
1489 : : }
1487 tgl@sss.pgh.pa.us 1490 [ + + ]:CBC 556 : else if (ncategory != pcategory)
1491 : : {
1492 : : /*
1493 : : * both types in different categories? then not much hope...
1494 : : */
1495 [ + - ]: 310 : if (noerror)
1496 : 310 : return InvalidOid;
1487 tgl@sss.pgh.pa.us 1497 [ # # ]:UBC 0 : ereport(ERROR,
1498 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1499 : : errmsg("argument types %s and %s cannot be matched",
1500 : : format_type_be(ptype),
1501 : : format_type_be(ntype))));
1502 : : }
1487 tgl@sss.pgh.pa.us 1503 [ + + + + ]:CBC 456 : else if (!pispreferred &&
1504 : 210 : can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
1505 [ + - ]: 135 : !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
1506 : : {
1507 : : /*
1508 : : * take new type if can coerce to it implicitly but not the
1509 : : * other way; but if we have a preferred type, stay on it.
1510 : : */
1511 : 135 : ptype = ntype;
1512 : 135 : pcategory = ncategory;
1513 : 135 : pispreferred = nispreferred;
1514 : : }
1515 : : }
1516 : : }
1517 : :
1518 : : /* Like select_common_type(), choose TEXT if all inputs were UNKNOWN */
1519 [ - + ]: 225 : if (ptype == UNKNOWNOID)
1487 tgl@sss.pgh.pa.us 1520 :UBC 0 : ptype = TEXTOID;
1521 : :
1487 tgl@sss.pgh.pa.us 1522 :CBC 225 : return ptype;
1523 : : }
1524 : :
1525 : : /*
1526 : : * coerce_to_common_type()
1527 : : * Coerce an expression to the given type.
1528 : : *
1529 : : * This is used following select_common_type() to coerce the individual
1530 : : * expressions to the desired type. 'context' is a phrase to use in the
1531 : : * error message if we fail to coerce.
1532 : : *
1533 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1534 : : * processing is wanted.
1535 : : */
1536 : : Node *
7656 1537 : 168107 : coerce_to_common_type(ParseState *pstate, Node *node,
1538 : : Oid targetTypeId, const char *context)
1539 : : {
8592 1540 : 168107 : Oid inputTypeId = exprType(node);
1541 : :
1542 [ + + ]: 168107 : if (inputTypeId == targetTypeId)
1543 : 107155 : return node; /* no work */
7879 1544 [ + - ]: 60952 : if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
7242 1545 : 60952 : node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
1546 : : COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
1547 : : else
7575 tgl@sss.pgh.pa.us 1548 [ # # ]:UBC 0 : ereport(ERROR,
1549 : : (errcode(ERRCODE_CANNOT_COERCE),
1550 : : /* translator: first %s is name of a SQL construct, eg CASE */
1551 : : errmsg("%s could not convert type %s to %s",
1552 : : context,
1553 : : format_type_be(inputTypeId),
1554 : : format_type_be(targetTypeId)),
1555 : : parser_errposition(pstate, exprLocation(node))));
8592 tgl@sss.pgh.pa.us 1556 :CBC 60949 : return node;
1557 : : }
1558 : :
1559 : : /*
1560 : : * verify_common_type()
1561 : : * Verify that all input types can be coerced to a proposed common type.
1562 : : * Return true if so, false if not all coercions are possible.
1563 : : *
1564 : : * Most callers of select_common_type() don't need to do this explicitly
1565 : : * because the checks will happen while trying to convert input expressions
1566 : : * to the right type, e.g. in coerce_to_common_type(). However, if a separate
1567 : : * check step is needed to validate the applicability of the common type, call
1568 : : * this.
1569 : : */
1570 : : bool
806 1571 : 7357 : verify_common_type(Oid common_type, List *exprs)
1572 : : {
1573 : : ListCell *lc;
1574 : :
1575 [ + - + + : 36964 : foreach(lc, exprs)
+ + ]
1576 : : {
1577 : 29610 : Node *nexpr = (Node *) lfirst(lc);
1578 : 29610 : Oid ntype = exprType(nexpr);
1579 : :
1580 [ + + ]: 29610 : if (!can_coerce_type(1, &ntype, &common_type, COERCION_IMPLICIT))
1581 : 3 : return false;
1582 : : }
1583 : 7354 : return true;
1584 : : }
1585 : :
1586 : : /*
1587 : : * verify_common_type_from_oids()
1588 : : * As above, but work from an array of type OIDs.
1589 : : */
1590 : : static bool
1591 : 3132 : verify_common_type_from_oids(Oid common_type, int nargs, const Oid *typeids)
1592 : : {
1593 [ + + ]: 8162 : for (int i = 0; i < nargs; i++)
1594 : : {
1595 [ + + ]: 5036 : if (!can_coerce_type(1, &typeids[i], &common_type, COERCION_IMPLICIT))
1596 : 6 : return false;
1597 : : }
1598 : 3126 : return true;
1599 : : }
1600 : :
1601 : : /*
1602 : : * select_common_typmod()
1603 : : * Determine the common typmod of a list of input expressions.
1604 : : *
1605 : : * common_type is the selected common type of the expressions, typically
1606 : : * computed using select_common_type().
1607 : : */
1608 : : int32
1265 peter@eisentraut.org 1609 : 28250 : select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
1610 : : {
1611 : : ListCell *lc;
1612 : 28250 : bool first = true;
1613 : 28250 : int32 result = -1;
1614 : :
1615 [ + - + + : 91048 : foreach(lc, exprs)
+ + ]
1616 : : {
1196 tgl@sss.pgh.pa.us 1617 : 62909 : Node *expr = (Node *) lfirst(lc);
1618 : :
1619 : : /* Types must match */
1265 peter@eisentraut.org 1620 [ + + ]: 62909 : if (exprType(expr) != common_type)
1621 : 111 : return -1;
1622 [ + + ]: 62819 : else if (first)
1623 : : {
1624 : 28205 : result = exprTypmod(expr);
1625 : 28205 : first = false;
1626 : : }
1627 : : else
1628 : : {
1629 : : /* As soon as we see a non-matching typmod, fall back to -1 */
1630 [ + + ]: 34614 : if (result != exprTypmod(expr))
1631 : 21 : return -1;
1632 : : }
1633 : : }
1634 : :
1635 : 28139 : return result;
1636 : : }
1637 : :
1638 : : /*
1639 : : * check_generic_type_consistency()
1640 : : * Are the actual arguments potentially compatible with a
1641 : : * polymorphic function?
1642 : : *
1643 : : * The argument consistency rules are:
1644 : : *
1645 : : * 1) All arguments declared ANYELEMENT must have the same datatype.
1646 : : * 2) All arguments declared ANYARRAY must have the same datatype,
1647 : : * which must be a varlena array type.
1648 : : * 3) All arguments declared ANYRANGE must be the same range type.
1649 : : * Similarly, all arguments declared ANYMULTIRANGE must be the same
1650 : : * multirange type; and if both of these appear, the ANYRANGE type
1651 : : * must be the element type of the ANYMULTIRANGE type.
1652 : : * 4) If there are arguments of more than one of these polymorphic types,
1653 : : * the array element type and/or range subtype must be the same as each
1654 : : * other and the same as the ANYELEMENT type.
1655 : : * 5) ANYENUM is treated the same as ANYELEMENT except that if it is used
1656 : : * (alone or in combination with plain ANYELEMENT), we add the extra
1657 : : * condition that the ANYELEMENT type must be an enum.
1658 : : * 6) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
1659 : : * we add the extra condition that the ANYELEMENT type must not be an array.
1660 : : * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
1661 : : * is an extra restriction if not.)
1662 : : * 7) All arguments declared ANYCOMPATIBLE must be implicitly castable
1663 : : * to a common supertype (chosen as per select_common_type's rules).
1664 : : * ANYCOMPATIBLENONARRAY works like ANYCOMPATIBLE but also requires the
1665 : : * common supertype to not be an array. If there are ANYCOMPATIBLEARRAY
1666 : : * or ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE arguments, their element
1667 : : * types or subtypes are included while making the choice of common supertype.
1668 : : * 8) The resolved type of ANYCOMPATIBLEARRAY arguments will be the array
1669 : : * type over the common supertype (which might not be the same array type
1670 : : * as any of the original arrays).
1671 : : * 9) All ANYCOMPATIBLERANGE arguments must be the exact same range type
1672 : : * (after domain flattening), since we have no preference rule that would
1673 : : * let us choose one over another. Furthermore, that range's subtype
1674 : : * must exactly match the common supertype chosen by rule 7.
1675 : : * 10) All ANYCOMPATIBLEMULTIRANGE arguments must be the exact same multirange
1676 : : * type (after domain flattening), since we have no preference rule that
1677 : : * would let us choose one over another. Furthermore, if ANYCOMPATIBLERANGE
1678 : : * also appears, that range type must be the multirange's element type;
1679 : : * otherwise, the multirange's range's subtype must exactly match the
1680 : : * common supertype chosen by rule 7.
1681 : : *
1682 : : * Domains over arrays match ANYARRAY, and are immediately flattened to their
1683 : : * base type. (Thus, for example, we will consider it a match if one ANYARRAY
1684 : : * argument is a domain over int4[] while another one is just int4[].) Also
1685 : : * notice that such a domain does *not* match ANYNONARRAY. The same goes
1686 : : * for ANYCOMPATIBLEARRAY and ANYCOMPATIBLENONARRAY.
1687 : : *
1688 : : * Similarly, domains over ranges match ANYRANGE or ANYCOMPATIBLERANGE,
1689 : : * and are immediately flattened to their base type. Likewise, domains
1690 : : * over multiranges match ANYMULTIRANGE or ANYCOMPATIBLEMULTIRANGE and are
1691 : : * immediately flattened to their base type.
1692 : : *
1693 : : * Note that domains aren't currently considered to match ANYENUM,
1694 : : * even if their base type would match.
1695 : : *
1696 : : * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
1697 : : * argument, assume it is okay.
1698 : : *
1699 : : * We do not ereport here, but just return false if a rule is violated.
1700 : : */
1701 : : bool
2000 peter_e@gmx.net 1702 : 60753 : check_generic_type_consistency(const Oid *actual_arg_types,
1703 : : const Oid *declared_arg_types,
1704 : : int nargs)
1705 : : {
7677 tgl@sss.pgh.pa.us 1706 : 60753 : Oid elem_typeid = InvalidOid;
1707 : 60753 : Oid array_typeid = InvalidOid;
4546 heikki.linnakangas@i 1708 : 60753 : Oid range_typeid = InvalidOid;
1211 akorotkov@postgresql 1709 : 60753 : Oid multirange_typeid = InvalidOid;
1487 tgl@sss.pgh.pa.us 1710 : 60753 : Oid anycompatible_range_typeid = InvalidOid;
1711 : 60753 : Oid anycompatible_range_typelem = InvalidOid;
1211 akorotkov@postgresql 1712 : 60753 : Oid anycompatible_multirange_typeid = InvalidOid;
1713 : 60753 : Oid anycompatible_multirange_typelem = InvalidOid;
1714 : 60753 : Oid range_typelem = InvalidOid;
6157 tgl@sss.pgh.pa.us 1715 : 60753 : bool have_anynonarray = false;
6222 1716 : 60753 : bool have_anyenum = false;
1487 1717 : 60753 : bool have_anycompatible_nonarray = false;
1718 : 60753 : int n_anycompatible_args = 0;
1719 : : Oid anycompatible_actual_types[FUNC_MAX_ARGS];
1720 : :
1721 : : /*
1722 : : * Loop through the arguments to see if we have any that are polymorphic.
1723 : : * If so, require the actual types to be consistent.
1724 : : */
1725 [ - + ]: 60753 : Assert(nargs <= FUNC_MAX_ARGS);
1489 1726 [ + + ]: 141581 : for (int j = 0; j < nargs; j++)
1727 : : {
6157 1728 : 97082 : Oid decl_type = declared_arg_types[j];
7559 bruce@momjian.us 1729 : 97082 : Oid actual_type = actual_arg_types[j];
1730 : :
6157 tgl@sss.pgh.pa.us 1731 [ + + + + ]: 97082 : if (decl_type == ANYELEMENTOID ||
1732 [ + + ]: 85742 : decl_type == ANYNONARRAYOID ||
1733 : : decl_type == ANYENUMOID)
1734 : : {
1735 [ + + ]: 21758 : if (decl_type == ANYNONARRAYOID)
1736 : 8135 : have_anynonarray = true;
1737 [ + + ]: 13623 : else if (decl_type == ANYENUMOID)
6222 1738 : 10418 : have_anyenum = true;
7677 1739 [ + + ]: 21758 : if (actual_type == UNKNOWNOID)
1740 : 1182 : continue;
1741 [ + + + + ]: 20576 : if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
1742 : 3645 : return false;
1743 : 16931 : elem_typeid = actual_type;
1744 : : }
6157 1745 [ + + ]: 75324 : else if (decl_type == ANYARRAYOID)
1746 : : {
7677 1747 [ + + ]: 28707 : if (actual_type == UNKNOWNOID)
1748 : 1294 : continue;
2489 1749 : 27413 : actual_type = getBaseType(actual_type); /* flatten domains */
7677 1750 [ + + + + ]: 27413 : if (OidIsValid(array_typeid) && actual_type != array_typeid)
1751 : 3638 : return false;
1752 : 23775 : array_typeid = actual_type;
1753 : : }
4546 heikki.linnakangas@i 1754 [ + + ]: 46617 : else if (decl_type == ANYRANGEOID)
1755 : : {
1756 [ + + ]: 15930 : if (actual_type == UNKNOWNOID)
1757 : 951 : continue;
2489 tgl@sss.pgh.pa.us 1758 : 14979 : actual_type = getBaseType(actual_type); /* flatten domains */
4546 heikki.linnakangas@i 1759 [ + + + + ]: 14979 : if (OidIsValid(range_typeid) && actual_type != range_typeid)
1760 : 4044 : return false;
1761 : 10935 : range_typeid = actual_type;
1762 : : }
1211 akorotkov@postgresql 1763 [ + + ]: 30687 : else if (decl_type == ANYMULTIRANGEOID)
1764 : : {
1765 [ + + ]: 17736 : if (actual_type == UNKNOWNOID)
1766 : 960 : continue;
1767 : 16776 : actual_type = getBaseType(actual_type); /* flatten domains */
1768 [ + + + + ]: 16776 : if (OidIsValid(multirange_typeid) && actual_type != multirange_typeid)
1769 : 4041 : return false;
1770 : 12735 : multirange_typeid = actual_type;
1771 : : }
1487 tgl@sss.pgh.pa.us 1772 [ + + + + ]: 12951 : else if (decl_type == ANYCOMPATIBLEOID ||
1773 : : decl_type == ANYCOMPATIBLENONARRAYOID)
1774 : : {
1775 [ + + ]: 1921 : if (decl_type == ANYCOMPATIBLENONARRAYOID)
1776 : 18 : have_anycompatible_nonarray = true;
1777 [ + + ]: 1921 : if (actual_type == UNKNOWNOID)
1778 : 676 : continue;
1779 : : /* collect the actual types of non-unknown COMPATIBLE args */
1780 : 1245 : anycompatible_actual_types[n_anycompatible_args++] = actual_type;
1781 : : }
1782 [ + + ]: 11030 : else if (decl_type == ANYCOMPATIBLEARRAYOID)
1783 : : {
1784 : : Oid elem_type;
1785 : :
1786 [ + + ]: 2763 : if (actual_type == UNKNOWNOID)
1787 : 448 : continue;
1788 : 2315 : actual_type = getBaseType(actual_type); /* flatten domains */
1789 : 2315 : elem_type = get_element_type(actual_type);
1790 [ + + ]: 2315 : if (!OidIsValid(elem_type))
1791 : 874 : return false; /* not an array */
1792 : : /* collect the element type for common-supertype choice */
1793 : 1441 : anycompatible_actual_types[n_anycompatible_args++] = elem_type;
1794 : : }
1795 [ + + ]: 8267 : else if (decl_type == ANYCOMPATIBLERANGEOID)
1796 : : {
1797 [ + + ]: 93 : if (actual_type == UNKNOWNOID)
1798 : 6 : continue;
1799 : 87 : actual_type = getBaseType(actual_type); /* flatten domains */
1800 [ + + ]: 87 : if (OidIsValid(anycompatible_range_typeid))
1801 : : {
1802 : : /* All ANYCOMPATIBLERANGE arguments must be the same type */
1803 [ + + ]: 6 : if (anycompatible_range_typeid != actual_type)
1804 : 3 : return false;
1805 : : }
1806 : : else
1807 : : {
1808 : 81 : anycompatible_range_typeid = actual_type;
1809 : 81 : anycompatible_range_typelem = get_range_subtype(actual_type);
1810 [ + + ]: 81 : if (!OidIsValid(anycompatible_range_typelem))
1811 : 3 : return false; /* not a range type */
1812 : : /* collect the subtype for common-supertype choice */
1813 : 78 : anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
1814 : : }
1815 : : }
1211 akorotkov@postgresql 1816 [ + + ]: 8174 : else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
1817 : : {
1818 [ + + ]: 69 : if (actual_type == UNKNOWNOID)
1819 : 9 : continue;
1820 : 60 : actual_type = getBaseType(actual_type); /* flatten domains */
1821 [ + + ]: 60 : if (OidIsValid(anycompatible_multirange_typeid))
1822 : : {
1823 : : /* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
1824 [ + + ]: 6 : if (anycompatible_multirange_typeid != actual_type)
1825 : 3 : return false;
1826 : : }
1827 : : else
1828 : : {
1829 : 54 : anycompatible_multirange_typeid = actual_type;
1830 : 54 : anycompatible_multirange_typelem = get_multirange_range(actual_type);
1831 [ + + ]: 54 : if (!OidIsValid(anycompatible_multirange_typelem))
1832 : 3 : return false; /* not a multirange type */
1833 : : /* we'll consider the subtype below */
1834 : : }
1835 : : }
1836 : : }
1837 : :
1838 : : /* Get the element type based on the array type, if we have one */
7677 tgl@sss.pgh.pa.us 1839 [ + + ]: 44499 : if (OidIsValid(array_typeid))
1840 : : {
7509 1841 [ + - ]: 18950 : if (array_typeid == ANYARRAYOID)
1842 : : {
1843 : : /*
1844 : : * Special case for matching ANYARRAY input to an ANYARRAY
1845 : : * argument: allow it for now. enforce_generic_type_consistency()
1846 : : * might complain later, depending on the presence of other
1847 : : * polymorphic arguments or results, but it will deliver a less
1848 : : * surprising error message than "function does not exist".
1849 : : *
1850 : : * (If you think to change this, note that can_coerce_type will
1851 : : * consider such a situation as a match, so that we might not even
1852 : : * get here.)
1853 : : */
1854 : : }
1855 : : else
1856 : : {
1857 : : Oid array_typelem;
1858 : :
1489 1859 : 18950 : array_typelem = get_element_type(array_typeid);
1860 [ + + ]: 18950 : if (!OidIsValid(array_typelem))
1861 : 8048 : return false; /* should be an array, but isn't */
1862 : :
1863 [ + + ]: 10902 : if (!OidIsValid(elem_typeid))
1864 : : {
1865 : : /*
1866 : : * if we don't have an element type yet, use the one we just
1867 : : * got
1868 : : */
1869 : 10838 : elem_typeid = array_typelem;
1870 : : }
1871 [ + + ]: 64 : else if (array_typelem != elem_typeid)
1872 : : {
1873 : : /* otherwise, they better match */
1874 : 24 : return false;
1875 : : }
1876 : : }
1877 : : }
1878 : :
1879 : : /* Deduce range type from multirange type, or check that they agree */
1211 akorotkov@postgresql 1880 [ + + ]: 36427 : if (OidIsValid(multirange_typeid))
1881 : : {
1882 : : Oid multirange_typelem;
1883 : :
1884 : 7361 : multirange_typelem = get_multirange_range(multirange_typeid);
1885 [ + + ]: 7361 : if (!OidIsValid(multirange_typelem))
1886 : 6379 : return false; /* should be a multirange, but isn't */
1887 : :
1888 [ + + ]: 982 : if (!OidIsValid(range_typeid))
1889 : : {
1890 : : /* If we don't have a range type yet, use the one we just got */
1891 : 723 : range_typeid = multirange_typelem;
1892 : 723 : range_typelem = get_range_subtype(multirange_typelem);
1893 [ - + ]: 723 : if (!OidIsValid(range_typelem))
1211 akorotkov@postgresql 1894 :UBC 0 : return false; /* should be a range, but isn't */
1895 : : }
1211 akorotkov@postgresql 1896 [ + + ]:CBC 259 : else if (multirange_typelem != range_typeid)
1897 : : {
1898 : : /* otherwise, they better match */
1899 : 147 : return false;
1900 : : }
1901 : : }
1902 : :
1903 : : /* Get the element type based on the range type, if we have one */
992 tgl@sss.pgh.pa.us 1904 [ + + ]: 29901 : if (OidIsValid(range_typeid))
1905 : : {
1906 : 4965 : range_typelem = get_range_subtype(range_typeid);
1907 [ + + ]: 4965 : if (!OidIsValid(range_typelem))
1908 : 2543 : return false; /* should be a range, but isn't */
1909 : :
1211 akorotkov@postgresql 1910 [ + + ]: 2422 : if (!OidIsValid(elem_typeid))
1911 : : {
1912 : : /*
1913 : : * If we don't have an element type yet, use the one we just got
1914 : : */
1915 : 2232 : elem_typeid = range_typelem;
1916 : : }
1917 [ + + ]: 190 : else if (range_typelem != elem_typeid)
1918 : : {
1919 : : /* otherwise, they better match */
1920 : 88 : return false;
1921 : : }
1922 : : }
1923 : :
4529 tgl@sss.pgh.pa.us 1924 [ + + ]: 27270 : if (have_anynonarray)
1925 : : {
1926 : : /* require the element type to not be an array or domain over array */
1927 [ + + ]: 7959 : if (type_is_array_domain(elem_typeid))
1928 : 115 : return false;
1929 : : }
1930 : :
1931 [ + + ]: 27155 : if (have_anyenum)
1932 : : {
1933 : : /* require the element type to be an enum */
1934 [ + + ]: 1671 : if (!type_is_enum(elem_typeid))
1935 : 1476 : return false;
1936 : : }
1937 : :
1938 : : /* Deduce range type from multirange type, or check that they agree */
992 1939 [ + + ]: 25679 : if (OidIsValid(anycompatible_multirange_typeid))
1940 : : {
1941 [ + + ]: 48 : if (OidIsValid(anycompatible_range_typeid))
1942 : : {
1943 [ + + ]: 6 : if (anycompatible_multirange_typelem !=
1944 : : anycompatible_range_typeid)
1945 : 3 : return false;
1946 : : }
1947 : : else
1948 : : {
1949 : 42 : anycompatible_range_typeid = anycompatible_multirange_typelem;
1950 : 42 : anycompatible_range_typelem = get_range_subtype(anycompatible_range_typeid);
1951 [ - + ]: 42 : if (!OidIsValid(anycompatible_range_typelem))
992 tgl@sss.pgh.pa.us 1952 :UBC 0 : return false; /* not a range type */
1953 : : /* collect the subtype for common-supertype choice */
992 tgl@sss.pgh.pa.us 1954 :CBC 42 : anycompatible_actual_types[n_anycompatible_args++] =
1955 : : anycompatible_range_typelem;
1956 : : }
1957 : : }
1958 : :
1959 : : /* Check matching of ANYCOMPATIBLE-family arguments, if any */
1487 1960 [ + + ]: 25676 : if (n_anycompatible_args > 0)
1961 : : {
1962 : : Oid anycompatible_typeid;
1963 : :
1964 : : anycompatible_typeid =
1965 : 1654 : select_common_type_from_oids(n_anycompatible_args,
1966 : : anycompatible_actual_types,
1967 : : true);
1968 : :
1969 [ + + ]: 1654 : if (!OidIsValid(anycompatible_typeid))
806 1970 : 310 : return false; /* there's definitely no common supertype */
1971 : :
1972 : : /* We have to verify that the selected type actually works */
1973 [ + + ]: 1344 : if (!verify_common_type_from_oids(anycompatible_typeid,
1974 : : n_anycompatible_args,
1975 : : anycompatible_actual_types))
1976 : 6 : return false;
1977 : :
1487 1978 [ + + ]: 1338 : if (have_anycompatible_nonarray)
1979 : : {
1980 : : /*
1981 : : * require the anycompatible type to not be an array or domain
1982 : : * over array
1983 : : */
1984 [ + + ]: 9 : if (type_is_array_domain(anycompatible_typeid))
1985 : 3 : return false;
1986 : : }
1987 : :
1988 : : /*
1989 : : * The anycompatible type must exactly match the range element type,
1990 : : * if we were able to identify one. This checks compatibility for
1991 : : * anycompatiblemultirange too since that also sets
1992 : : * anycompatible_range_typelem above.
1993 : : */
1994 [ + + + + ]: 1335 : if (OidIsValid(anycompatible_range_typelem) &&
1995 : : anycompatible_range_typelem != anycompatible_typeid)
1996 : 21 : return false;
1997 : : }
1998 : :
1999 : : /* Looks valid */
7677 2000 : 25336 : return true;
2001 : : }
2002 : :
2003 : : /*
2004 : : * enforce_generic_type_consistency()
2005 : : * Make sure a polymorphic function is legally callable, and
2006 : : * deduce actual argument and result types.
2007 : : *
2008 : : * If any polymorphic pseudotype is used in a function's arguments or
2009 : : * return type, we make sure the actual data types are consistent with
2010 : : * each other. The argument consistency rules are shown above for
2011 : : * check_generic_type_consistency().
2012 : : *
2013 : : * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
2014 : : * argument, we attempt to deduce the actual type it should have. If
2015 : : * successful, we alter that position of declared_arg_types[] so that
2016 : : * make_fn_arguments will coerce the literal to the right thing.
2017 : : *
2018 : : * If we have polymorphic arguments of the ANYCOMPATIBLE family,
2019 : : * we similarly alter declared_arg_types[] entries to show the resolved
2020 : : * common supertype, so that make_fn_arguments will coerce the actual
2021 : : * arguments to the proper type.
2022 : : *
2023 : : * Rules are applied to the function's return type (possibly altering it)
2024 : : * if it is declared as a polymorphic type and there is at least one
2025 : : * polymorphic argument type:
2026 : : *
2027 : : * 1) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
2028 : : * argument's actual type as the function's return type.
2029 : : * 2) If return type is ANYARRAY, and any argument is ANYARRAY, use the
2030 : : * argument's actual type as the function's return type.
2031 : : * 3) Similarly, if return type is ANYRANGE or ANYMULTIRANGE, and any
2032 : : * argument is ANYRANGE or ANYMULTIRANGE, use that argument's actual type
2033 : : * (or the corresponding range or multirange type) as the function's return
2034 : : * type.
2035 : : * 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, and there is
2036 : : * at least one ANYELEMENT, ANYARRAY, ANYRANGE, or ANYMULTIRANGE input,
2037 : : * deduce the return type from those inputs, or throw error if we can't.
2038 : : * 5) Otherwise, if return type is ANYRANGE or ANYMULTIRANGE, throw error.
2039 : : * (We have no way to select a specific range type if the arguments don't
2040 : : * include ANYRANGE or ANYMULTIRANGE.)
2041 : : * 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
2042 : : * (alone or in combination with plain ANYELEMENT), we add the extra
2043 : : * condition that the ANYELEMENT type must be an enum.
2044 : : * 7) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
2045 : : * we add the extra condition that the ANYELEMENT type must not be an array.
2046 : : * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
2047 : : * is an extra restriction if not.)
2048 : : * 8) ANYCOMPATIBLE, ANYCOMPATIBLEARRAY, and ANYCOMPATIBLENONARRAY are handled
2049 : : * by resolving the common supertype of those arguments (or their element
2050 : : * types, for array inputs), and then coercing all those arguments to the
2051 : : * common supertype, or the array type over the common supertype for
2052 : : * ANYCOMPATIBLEARRAY.
2053 : : * 9) For ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE, there must be at
2054 : : * least one non-UNKNOWN input matching those arguments, and all such
2055 : : * inputs must be the same range type (or its multirange type, as
2056 : : * appropriate), since we cannot deduce a range type from non-range types.
2057 : : * Furthermore, the range type's subtype is included while choosing the
2058 : : * common supertype for ANYCOMPATIBLE et al, and it must exactly match
2059 : : * that common supertype.
2060 : : *
2061 : : * Domains over arrays or ranges match ANYARRAY or ANYRANGE arguments,
2062 : : * respectively, and are immediately flattened to their base type. (In
2063 : : * particular, if the return type is also ANYARRAY or ANYRANGE, we'll set
2064 : : * it to the base type not the domain type.) The same is true for
2065 : : * ANYMULTIRANGE, ANYCOMPATIBLEARRAY, ANYCOMPATIBLERANGE, and
2066 : : * ANYCOMPATIBLEMULTIRANGE.
2067 : : *
2068 : : * When allow_poly is false, we are not expecting any of the actual_arg_types
2069 : : * to be polymorphic, and we should not return a polymorphic result type
2070 : : * either. When allow_poly is true, it is okay to have polymorphic "actual"
2071 : : * arg types, and we can return a matching polymorphic type as the result.
2072 : : * (This case is currently used only to check compatibility of an aggregate's
2073 : : * declaration with the underlying transfn.)
2074 : : *
2075 : : * A special case is that we could see ANYARRAY as an actual_arg_type even
2076 : : * when allow_poly is false (this is possible only because pg_statistic has
2077 : : * columns shown as anyarray in the catalogs). We allow this to match a
2078 : : * declared ANYARRAY argument, but only if there is no other polymorphic
2079 : : * argument that we would need to match it with, and no need to determine
2080 : : * the element type to infer the result type. Note this means that functions
2081 : : * taking ANYARRAY had better behave sanely if applied to the pg_statistic
2082 : : * columns; they can't just assume that successive inputs are of the same
2083 : : * actual element type. There is no similar logic for ANYCOMPATIBLEARRAY;
2084 : : * there isn't a need for it since there are no catalog columns of that type,
2085 : : * so we won't see it as input. We could consider matching an actual ANYARRAY
2086 : : * input to an ANYCOMPATIBLEARRAY argument, but at present that seems useless
2087 : : * as well, since there's no value in using ANYCOMPATIBLEARRAY unless there's
2088 : : * at least one other ANYCOMPATIBLE-family argument or result.
2089 : : *
2090 : : * Also, if there are no arguments declared to be of polymorphic types,
2091 : : * we'll return the rettype unmodified even if it's polymorphic. This should
2092 : : * never occur for user-declared functions, because CREATE FUNCTION prevents
2093 : : * it. But it does happen for some built-in functions, such as array_in().
2094 : : */
2095 : : Oid
2000 peter_e@gmx.net 2096 : 478987 : enforce_generic_type_consistency(const Oid *actual_arg_types,
2097 : : Oid *declared_arg_types,
2098 : : int nargs,
2099 : : Oid rettype,
2100 : : bool allow_poly)
2101 : : {
1487 tgl@sss.pgh.pa.us 2102 : 478987 : bool have_poly_anycompatible = false;
1489 2103 : 478987 : bool have_poly_unknowns = false;
7677 2104 : 478987 : Oid elem_typeid = InvalidOid;
2105 : 478987 : Oid array_typeid = InvalidOid;
4546 heikki.linnakangas@i 2106 : 478987 : Oid range_typeid = InvalidOid;
1211 akorotkov@postgresql 2107 : 478987 : Oid multirange_typeid = InvalidOid;
1487 tgl@sss.pgh.pa.us 2108 : 478987 : Oid anycompatible_typeid = InvalidOid;
2109 : 478987 : Oid anycompatible_array_typeid = InvalidOid;
2110 : 478987 : Oid anycompatible_range_typeid = InvalidOid;
2111 : 478987 : Oid anycompatible_range_typelem = InvalidOid;
1211 akorotkov@postgresql 2112 : 478987 : Oid anycompatible_multirange_typeid = InvalidOid;
2113 : 478987 : Oid anycompatible_multirange_typelem = InvalidOid;
6157 tgl@sss.pgh.pa.us 2114 : 478987 : bool have_anynonarray = (rettype == ANYNONARRAYOID);
6222 2115 : 478987 : bool have_anyenum = (rettype == ANYENUMOID);
992 2116 : 478987 : bool have_anymultirange = (rettype == ANYMULTIRANGEOID);
1487 2117 : 478987 : bool have_anycompatible_nonarray = (rettype == ANYCOMPATIBLENONARRAYOID);
2118 : 478987 : bool have_anycompatible_array = (rettype == ANYCOMPATIBLEARRAYOID);
2119 : 478987 : bool have_anycompatible_range = (rettype == ANYCOMPATIBLERANGEOID);
992 2120 : 478987 : bool have_anycompatible_multirange = (rettype == ANYCOMPATIBLEMULTIRANGEOID);
1487 2121 : 478987 : int n_poly_args = 0; /* this counts all family-1 arguments */
2122 : 478987 : int n_anycompatible_args = 0; /* this counts only non-unknowns */
2123 : : Oid anycompatible_actual_types[FUNC_MAX_ARGS];
2124 : :
2125 : : /*
2126 : : * Loop through the arguments to see if we have any that are polymorphic.
2127 : : * If so, require the actual types to be consistent.
2128 : : */
2129 [ - + ]: 478987 : Assert(nargs <= FUNC_MAX_ARGS);
1489 2130 [ + + ]: 1372165 : for (int j = 0; j < nargs; j++)
2131 : : {
6157 2132 : 893178 : Oid decl_type = declared_arg_types[j];
7559 bruce@momjian.us 2133 : 893178 : Oid actual_type = actual_arg_types[j];
2134 : :
6157 tgl@sss.pgh.pa.us 2135 [ + + + + ]: 893178 : if (decl_type == ANYELEMENTOID ||
2136 [ + + ]: 882313 : decl_type == ANYNONARRAYOID ||
2137 : : decl_type == ANYENUMOID)
2138 : : {
1489 2139 : 11284 : n_poly_args++;
6157 2140 [ + + ]: 11284 : if (decl_type == ANYNONARRAYOID)
2141 : 7841 : have_anynonarray = true;
2142 [ + + ]: 3443 : else if (decl_type == ANYENUMOID)
6222 2143 : 419 : have_anyenum = true;
7677 2144 [ + + ]: 11284 : if (actual_type == UNKNOWNOID)
2145 : : {
1489 2146 : 360 : have_poly_unknowns = true;
7677 2147 : 360 : continue;
2148 : : }
5938 2149 [ + + + + ]: 10924 : if (allow_poly && decl_type == actual_type)
2150 : 88 : continue; /* no new information here */
7677 2151 [ + + - + ]: 10836 : if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
7575 tgl@sss.pgh.pa.us 2152 [ # # ]:UBC 0 : ereport(ERROR,
2153 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2154 : : errmsg("arguments declared \"%s\" are not all alike", "anyelement"),
2155 : : errdetail("%s versus %s",
2156 : : format_type_be(elem_typeid),
2157 : : format_type_be(actual_type))));
7677 tgl@sss.pgh.pa.us 2158 :CBC 10836 : elem_typeid = actual_type;
2159 : : }
6157 2160 [ + + ]: 881894 : else if (decl_type == ANYARRAYOID)
2161 : : {
1489 2162 : 15544 : n_poly_args++;
7677 2163 [ + + ]: 15544 : if (actual_type == UNKNOWNOID)
2164 : : {
1489 2165 : 1980 : have_poly_unknowns = true;
7677 2166 : 1980 : continue;
2167 : : }
5938 2168 [ + + + + ]: 13564 : if (allow_poly && decl_type == actual_type)
2169 : 49 : continue; /* no new information here */
2489 2170 : 13515 : actual_type = getBaseType(actual_type); /* flatten domains */
7677 2171 [ + + - + ]: 13515 : if (OidIsValid(array_typeid) && actual_type != array_typeid)
7575 tgl@sss.pgh.pa.us 2172 [ # # ]:UBC 0 : ereport(ERROR,
2173 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2174 : : errmsg("arguments declared \"%s\" are not all alike", "anyarray"),
2175 : : errdetail("%s versus %s",
2176 : : format_type_be(array_typeid),
2177 : : format_type_be(actual_type))));
7677 tgl@sss.pgh.pa.us 2178 :CBC 13515 : array_typeid = actual_type;
2179 : : }
4546 heikki.linnakangas@i 2180 [ + + ]: 866350 : else if (decl_type == ANYRANGEOID)
2181 : : {
1489 tgl@sss.pgh.pa.us 2182 : 3553 : n_poly_args++;
4546 heikki.linnakangas@i 2183 [ + + ]: 3553 : if (actual_type == UNKNOWNOID)
2184 : : {
1489 tgl@sss.pgh.pa.us 2185 : 236 : have_poly_unknowns = true;
4546 heikki.linnakangas@i 2186 : 236 : continue;
2187 : : }
2188 [ - + - - ]: 3317 : if (allow_poly && decl_type == actual_type)
4546 heikki.linnakangas@i 2189 :UBC 0 : continue; /* no new information here */
2489 tgl@sss.pgh.pa.us 2190 :CBC 3317 : actual_type = getBaseType(actual_type); /* flatten domains */
4546 heikki.linnakangas@i 2191 [ + + - + ]: 3317 : if (OidIsValid(range_typeid) && actual_type != range_typeid)
4546 heikki.linnakangas@i 2192 [ # # ]:UBC 0 : ereport(ERROR,
2193 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2194 : : errmsg("arguments declared \"%s\" are not all alike", "anyrange"),
2195 : : errdetail("%s versus %s",
2196 : : format_type_be(range_typeid),
2197 : : format_type_be(actual_type))));
4546 heikki.linnakangas@i 2198 :CBC 3317 : range_typeid = actual_type;
2199 : : }
1211 akorotkov@postgresql 2200 [ + + ]: 862797 : else if (decl_type == ANYMULTIRANGEOID)
2201 : : {
2202 : 2416 : n_poly_args++;
992 tgl@sss.pgh.pa.us 2203 : 2416 : have_anymultirange = true;
1211 akorotkov@postgresql 2204 [ + + ]: 2416 : if (actual_type == UNKNOWNOID)
2205 : : {
2206 : 132 : have_poly_unknowns = true;
2207 : 132 : continue;
2208 : : }
2209 [ - + - - ]: 2284 : if (allow_poly && decl_type == actual_type)
1211 akorotkov@postgresql 2210 :UBC 0 : continue; /* no new information here */
1211 akorotkov@postgresql 2211 :CBC 2284 : actual_type = getBaseType(actual_type); /* flatten domains */
2212 [ + + - + ]: 2284 : if (OidIsValid(multirange_typeid) && actual_type != multirange_typeid)
1211 akorotkov@postgresql 2213 [ # # ]:UBC 0 : ereport(ERROR,
2214 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2215 : : errmsg("arguments declared \"%s\" are not all alike", "anymultirange"),
2216 : : errdetail("%s versus %s",
2217 : : format_type_be(multirange_typeid),
2218 : : format_type_be(actual_type))));
1211 akorotkov@postgresql 2219 :CBC 2284 : multirange_typeid = actual_type;
2220 : : }
1487 tgl@sss.pgh.pa.us 2221 [ + + + + ]: 860381 : else if (decl_type == ANYCOMPATIBLEOID ||
2222 : : decl_type == ANYCOMPATIBLENONARRAYOID)
2223 : : {
2224 : 1053 : have_poly_anycompatible = true;
2225 [ + + ]: 1053 : if (decl_type == ANYCOMPATIBLENONARRAYOID)
2226 : 12 : have_anycompatible_nonarray = true;
2227 [ + + ]: 1053 : if (actual_type == UNKNOWNOID)
2228 : 484 : continue;
2229 [ + + + + ]: 569 : if (allow_poly && decl_type == actual_type)
2230 : 4 : continue; /* no new information here */
2231 : : /* collect the actual types of non-unknown COMPATIBLE args */
2232 : 565 : anycompatible_actual_types[n_anycompatible_args++] = actual_type;
2233 : : }
2234 [ + + ]: 859328 : else if (decl_type == ANYCOMPATIBLEARRAYOID)
2235 : : {
2236 : : Oid anycompatible_elem_type;
2237 : :
2238 : 2417 : have_poly_anycompatible = true;
2239 : 2417 : have_anycompatible_array = true;
2240 [ + + ]: 2417 : if (actual_type == UNKNOWNOID)
2241 : 15 : continue;
2242 [ + + + + ]: 2402 : if (allow_poly && decl_type == actual_type)
2243 : 4 : continue; /* no new information here */
2244 : 2398 : actual_type = getBaseType(actual_type); /* flatten domains */
2245 : 2398 : anycompatible_elem_type = get_element_type(actual_type);
2246 [ - + ]: 2398 : if (!OidIsValid(anycompatible_elem_type))
1487 tgl@sss.pgh.pa.us 2247 [ # # ]:UBC 0 : ereport(ERROR,
2248 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2249 : : errmsg("argument declared %s is not an array but type %s",
2250 : : "anycompatiblearray",
2251 : : format_type_be(actual_type))));
2252 : : /* collect the element type for common-supertype choice */
1487 tgl@sss.pgh.pa.us 2253 :CBC 2398 : anycompatible_actual_types[n_anycompatible_args++] = anycompatible_elem_type;
2254 : : }
2255 [ + + ]: 856911 : else if (decl_type == ANYCOMPATIBLERANGEOID)
2256 : : {
2257 : 69 : have_poly_anycompatible = true;
2258 : 69 : have_anycompatible_range = true;
2259 [ + + ]: 69 : if (actual_type == UNKNOWNOID)
2260 : 6 : continue;
2261 [ - + - - ]: 63 : if (allow_poly && decl_type == actual_type)
1487 tgl@sss.pgh.pa.us 2262 :UBC 0 : continue; /* no new information here */
1487 tgl@sss.pgh.pa.us 2263 :CBC 63 : actual_type = getBaseType(actual_type); /* flatten domains */
2264 [ + + ]: 63 : if (OidIsValid(anycompatible_range_typeid))
2265 : : {
2266 : : /* All ANYCOMPATIBLERANGE arguments must be the same type */
2267 [ - + ]: 3 : if (anycompatible_range_typeid != actual_type)
1487 tgl@sss.pgh.pa.us 2268 [ # # ]:UBC 0 : ereport(ERROR,
2269 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2270 : : errmsg("arguments declared \"%s\" are not all alike", "anycompatiblerange"),
2271 : : errdetail("%s versus %s",
2272 : : format_type_be(anycompatible_range_typeid),
2273 : : format_type_be(actual_type))));
2274 : : }
2275 : : else
2276 : : {
1487 tgl@sss.pgh.pa.us 2277 :CBC 60 : anycompatible_range_typeid = actual_type;
2278 : 60 : anycompatible_range_typelem = get_range_subtype(actual_type);
2279 [ - + ]: 60 : if (!OidIsValid(anycompatible_range_typelem))
1487 tgl@sss.pgh.pa.us 2280 [ # # ]:UBC 0 : ereport(ERROR,
2281 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2282 : : errmsg("argument declared %s is not a range type but type %s",
2283 : : "anycompatiblerange",
2284 : : format_type_be(actual_type))));
2285 : : /* collect the subtype for common-supertype choice */
1487 tgl@sss.pgh.pa.us 2286 :CBC 60 : anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
2287 : : }
2288 : : }
1211 akorotkov@postgresql 2289 [ + + ]: 856842 : else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
2290 : : {
2291 : 48 : have_poly_anycompatible = true;
992 tgl@sss.pgh.pa.us 2292 : 48 : have_anycompatible_multirange = true;
1211 akorotkov@postgresql 2293 [ + + ]: 48 : if (actual_type == UNKNOWNOID)
2294 : 9 : continue;
2295 [ - + - - ]: 39 : if (allow_poly && decl_type == actual_type)
1211 akorotkov@postgresql 2296 :UBC 0 : continue; /* no new information here */
1211 akorotkov@postgresql 2297 :CBC 39 : actual_type = getBaseType(actual_type); /* flatten domains */
2298 [ + + ]: 39 : if (OidIsValid(anycompatible_multirange_typeid))
2299 : : {
2300 : : /* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
2301 [ - + ]: 3 : if (anycompatible_multirange_typeid != actual_type)
1211 akorotkov@postgresql 2302 [ # # ]:UBC 0 : ereport(ERROR,
2303 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2304 : : errmsg("arguments declared \"%s\" are not all alike", "anycompatiblemultirange"),
2305 : : errdetail("%s versus %s",
2306 : : format_type_be(anycompatible_multirange_typeid),
2307 : : format_type_be(actual_type))));
2308 : : }
2309 : : else
2310 : : {
1211 akorotkov@postgresql 2311 :CBC 36 : anycompatible_multirange_typeid = actual_type;
2312 : 36 : anycompatible_multirange_typelem = get_multirange_range(actual_type);
2313 [ - + ]: 36 : if (!OidIsValid(anycompatible_multirange_typelem))
1211 akorotkov@postgresql 2314 [ # # ]:UBC 0 : ereport(ERROR,
2315 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2316 : : errmsg("argument declared %s is not a multirange type but type %s",
2317 : : "anycompatiblemultirange",
2318 : : format_type_be(actual_type))));
2319 : : /* we'll consider the subtype below */
2320 : : }
2321 : : }
2322 : : }
2323 : :
2324 : : /*
2325 : : * Fast Track: if none of the arguments are polymorphic, return the
2326 : : * unmodified rettype. Not our job to resolve it if it's polymorphic.
2327 : : */
1487 tgl@sss.pgh.pa.us 2328 [ + + + + ]:CBC 478987 : if (n_poly_args == 0 && !have_poly_anycompatible)
7677 2329 : 450628 : return rettype;
2330 : :
2331 : : /* Check matching of family-1 polymorphic arguments, if any */
1489 2332 [ + + ]: 28359 : if (n_poly_args)
2333 : : {
2334 : : /* Get the element type based on the array type, if we have one */
2335 [ + + ]: 26582 : if (OidIsValid(array_typeid))
2336 : : {
2337 : : Oid array_typelem;
2338 : :
2339 [ + + ]: 12619 : if (array_typeid == ANYARRAYOID)
2340 : : {
2341 : : /*
2342 : : * Special case for matching ANYARRAY input to an ANYARRAY
2343 : : * argument: allow it iff no other arguments are family-1
2344 : : * polymorphics (otherwise we couldn't be sure whether the
2345 : : * array element type matches up) and the result type doesn't
2346 : : * require us to infer a specific element type.
2347 : : */
2348 [ + - + + ]: 21 : if (n_poly_args != 1 ||
1487 2349 [ + + ]: 9 : (rettype != ANYARRAYOID &&
2350 [ + - + - : 3 : IsPolymorphicTypeFamily1(rettype)))
+ - + - -
+ ]
1489 2351 [ + - ]: 6 : ereport(ERROR,
2352 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2353 : : errmsg("cannot determine element type of \"anyarray\" argument")));
2354 : 15 : array_typelem = ANYELEMENTOID;
2355 : : }
2356 : : else
2357 : : {
2358 : 12598 : array_typelem = get_element_type(array_typeid);
2359 [ - + ]: 12598 : if (!OidIsValid(array_typelem))
1489 tgl@sss.pgh.pa.us 2360 [ # # ]:UBC 0 : ereport(ERROR,
2361 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2362 : : errmsg("argument declared %s is not an array but type %s",
2363 : : "anyarray", format_type_be(array_typeid))));
2364 : : }
2365 : :
1489 tgl@sss.pgh.pa.us 2366 [ + + ]:CBC 12613 : if (!OidIsValid(elem_typeid))
2367 : : {
2368 : : /*
2369 : : * if we don't have an element type yet, use the one we just
2370 : : * got
2371 : : */
2372 : 12573 : elem_typeid = array_typelem;
2373 : : }
2374 [ - + ]: 40 : else if (array_typelem != elem_typeid)
2375 : : {
2376 : : /* otherwise, they better match */
5600 tgl@sss.pgh.pa.us 2377 [ # # ]:UBC 0 : ereport(ERROR,
2378 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2379 : : errmsg("argument declared %s is not consistent with argument declared %s",
2380 : : "anyarray", "anyelement"),
2381 : : errdetail("%s versus %s",
2382 : : format_type_be(array_typeid),
2383 : : format_type_be(elem_typeid))));
2384 : : }
2385 : : }
2386 : :
2387 : : /* Deduce range type from multirange type, or vice versa */
1211 akorotkov@postgresql 2388 [ + + ]:CBC 26576 : if (OidIsValid(multirange_typeid))
2389 : : {
2390 : : Oid multirange_typelem;
2391 : :
2392 : 1705 : multirange_typelem = get_multirange_range(multirange_typeid);
2393 [ - + ]: 1705 : if (!OidIsValid(multirange_typelem))
1211 akorotkov@postgresql 2394 [ # # ]:UBC 0 : ereport(ERROR,
2395 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2396 : : errmsg("argument declared %s is not a multirange type but type %s",
2397 : : "anymultirange",
2398 : : format_type_be(multirange_typeid))));
2399 : :
1211 akorotkov@postgresql 2400 [ + + ]:CBC 1705 : if (!OidIsValid(range_typeid))
2401 : : {
2402 : : /* if we don't have a range type yet, use the one we just got */
2403 : 1050 : range_typeid = multirange_typelem;
2404 : : }
2405 [ - + ]: 655 : else if (multirange_typelem != range_typeid)
2406 : : {
2407 : : /* otherwise, they better match */
1211 akorotkov@postgresql 2408 [ # # ]:UBC 0 : ereport(ERROR,
2409 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2410 : : errmsg("argument declared %s is not consistent with argument declared %s",
2411 : : "anymultirange", "anyrange"),
2412 : : errdetail("%s versus %s",
2413 : : format_type_be(multirange_typeid),
2414 : : format_type_be(range_typeid))));
2415 : : }
2416 : : }
992 tgl@sss.pgh.pa.us 2417 [ + + + + ]:CBC 24871 : else if (have_anymultirange && OidIsValid(range_typeid))
2418 : : {
2419 : 145 : multirange_typeid = get_range_multirange(range_typeid);
2420 : : /* We'll complain below if that didn't work */
2421 : : }
2422 : :
2423 : : /* Get the element type based on the range type, if we have one */
2424 [ + + ]: 26576 : if (OidIsValid(range_typeid))
2425 : : {
2426 : : Oid range_typelem;
2427 : :
2428 : 3432 : range_typelem = get_range_subtype(range_typeid);
2429 [ - + ]: 3432 : if (!OidIsValid(range_typelem))
992 tgl@sss.pgh.pa.us 2430 [ # # ]:UBC 0 : ereport(ERROR,
2431 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2432 : : errmsg("argument declared %s is not a range type but type %s",
2433 : : "anyrange",
2434 : : format_type_be(range_typeid))));
2435 : :
1211 akorotkov@postgresql 2436 [ + + ]:CBC 3432 : if (!OidIsValid(elem_typeid))
2437 : : {
2438 : : /*
2439 : : * if we don't have an element type yet, use the one we just
2440 : : * got
2441 : : */
2442 : 3255 : elem_typeid = range_typelem;
2443 : : }
2444 [ - + ]: 177 : else if (range_typelem != elem_typeid)
2445 : : {
2446 : : /* otherwise, they better match */
1211 akorotkov@postgresql 2447 [ # # ]:UBC 0 : ereport(ERROR,
2448 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2449 : : errmsg("argument declared %s is not consistent with argument declared %s",
2450 : : "anyrange", "anyelement"),
2451 : : errdetail("%s versus %s",
2452 : : format_type_be(range_typeid),
2453 : : format_type_be(elem_typeid))));
2454 : : }
2455 : : }
2456 : :
4546 heikki.linnakangas@i 2457 [ + + ]:CBC 26576 : if (!OidIsValid(elem_typeid))
2458 : : {
1489 tgl@sss.pgh.pa.us 2459 [ + + ]: 110 : if (allow_poly)
2460 : : {
2461 : 98 : elem_typeid = ANYELEMENTOID;
2462 : 98 : array_typeid = ANYARRAYOID;
2463 : 98 : range_typeid = ANYRANGEOID;
1211 akorotkov@postgresql 2464 : 98 : multirange_typeid = ANYMULTIRANGEOID;
2465 : : }
2466 : : else
2467 : : {
2468 : : /*
2469 : : * Only way to get here is if all the family-1 polymorphic
2470 : : * arguments have UNKNOWN inputs.
2471 : : */
1489 tgl@sss.pgh.pa.us 2472 [ + - ]: 12 : ereport(ERROR,
2473 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2474 : : errmsg("could not determine polymorphic type because input has type %s",
2475 : : "unknown")));
2476 : : }
2477 : : }
2478 : :
2479 [ + + + - ]: 26564 : if (have_anynonarray && elem_typeid != ANYELEMENTOID)
2480 : : {
2481 : : /*
2482 : : * require the element type to not be an array or domain over
2483 : : * array
2484 : : */
2485 [ - + ]: 7665 : if (type_is_array_domain(elem_typeid))
1489 tgl@sss.pgh.pa.us 2486 [ # # ]:UBC 0 : ereport(ERROR,
2487 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2488 : : errmsg("type matched to anynonarray is an array type: %s",
2489 : : format_type_be(elem_typeid))));
2490 : : }
2491 : :
1489 tgl@sss.pgh.pa.us 2492 [ + + + - ]:CBC 26564 : if (have_anyenum && elem_typeid != ANYELEMENTOID)
2493 : : {
2494 : : /* require the element type to be an enum */
2495 [ - + ]: 286 : if (!type_is_enum(elem_typeid))
1489 tgl@sss.pgh.pa.us 2496 [ # # ]:UBC 0 : ereport(ERROR,
2497 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2498 : : errmsg("type matched to anyenum is not an enum type: %s",
2499 : : format_type_be(elem_typeid))));
2500 : : }
2501 : : }
2502 : :
2503 : : /* Check matching of family-2 polymorphic arguments, if any */
1487 tgl@sss.pgh.pa.us 2504 [ + + ]:CBC 28341 : if (have_poly_anycompatible)
2505 : : {
2506 : : /* Deduce range type from multirange type, or vice versa */
992 2507 [ + + ]: 1804 : if (OidIsValid(anycompatible_multirange_typeid))
2508 : : {
2509 [ + + ]: 36 : if (OidIsValid(anycompatible_range_typeid))
2510 : : {
2511 [ - + ]: 3 : if (anycompatible_multirange_typelem !=
2512 : : anycompatible_range_typeid)
992 tgl@sss.pgh.pa.us 2513 [ # # ]:UBC 0 : ereport(ERROR,
2514 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2515 : : errmsg("argument declared %s is not consistent with argument declared %s",
2516 : : "anycompatiblemultirange",
2517 : : "anycompatiblerange"),
2518 : : errdetail("%s versus %s",
2519 : : format_type_be(anycompatible_multirange_typeid),
2520 : : format_type_be(anycompatible_range_typeid))));
2521 : : }
2522 : : else
2523 : : {
992 tgl@sss.pgh.pa.us 2524 :CBC 33 : anycompatible_range_typeid = anycompatible_multirange_typelem;
2525 : 33 : anycompatible_range_typelem = get_range_subtype(anycompatible_range_typeid);
2526 [ - + ]: 33 : if (!OidIsValid(anycompatible_range_typelem))
992 tgl@sss.pgh.pa.us 2527 [ # # ]:UBC 0 : ereport(ERROR,
2528 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2529 : : errmsg("argument declared %s is not a multirange type but type %s",
2530 : : "anycompatiblemultirange",
2531 : : format_type_be(anycompatible_multirange_typeid))));
2532 : : /* this enables element type matching check below */
992 tgl@sss.pgh.pa.us 2533 :CBC 33 : have_anycompatible_range = true;
2534 : : /* collect the subtype for common-supertype choice */
2535 : 33 : anycompatible_actual_types[n_anycompatible_args++] =
2536 : : anycompatible_range_typelem;
2537 : : }
2538 : : }
2539 [ + + + + ]: 1768 : else if (have_anycompatible_multirange &&
2540 : : OidIsValid(anycompatible_range_typeid))
2541 : : {
2542 : 3 : anycompatible_multirange_typeid = get_range_multirange(anycompatible_range_typeid);
2543 : : /* We'll complain below if that didn't work */
2544 : : }
2545 : :
1487 2546 [ + + ]: 1804 : if (n_anycompatible_args > 0)
2547 : : {
2548 : : anycompatible_typeid =
2549 : 1788 : select_common_type_from_oids(n_anycompatible_args,
2550 : : anycompatible_actual_types,
2551 : : false);
2552 : :
2553 : : /* We have to verify that the selected type actually works */
806 2554 [ - + ]: 1788 : if (!verify_common_type_from_oids(anycompatible_typeid,
2555 : : n_anycompatible_args,
2556 : : anycompatible_actual_types))
806 tgl@sss.pgh.pa.us 2557 [ # # ]:UBC 0 : ereport(ERROR,
2558 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2559 : : errmsg("arguments of anycompatible family cannot be cast to a common type")));
2560 : :
1487 tgl@sss.pgh.pa.us 2561 [ + + ]:CBC 1788 : if (have_anycompatible_array)
2562 : : {
2563 : 1689 : anycompatible_array_typeid = get_array_type(anycompatible_typeid);
2564 [ - + ]: 1689 : if (!OidIsValid(anycompatible_array_typeid))
1487 tgl@sss.pgh.pa.us 2565 [ # # ]:UBC 0 : ereport(ERROR,
2566 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
2567 : : errmsg("could not find array type for data type %s",
2568 : : format_type_be(anycompatible_typeid))));
2569 : : }
2570 : :
1487 tgl@sss.pgh.pa.us 2571 [ + + ]:CBC 1788 : if (have_anycompatible_range)
2572 : : {
2573 : : /* we can't infer a range type from the others */
2574 [ + + ]: 96 : if (!OidIsValid(anycompatible_range_typeid))
2575 [ + - ]: 3 : ereport(ERROR,
2576 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2577 : : errmsg("could not determine polymorphic type %s because input has type %s",
2578 : : "anycompatiblerange", "unknown")));
2579 : :
2580 : : /*
2581 : : * the anycompatible type must exactly match the range element
2582 : : * type
2583 : : */
2584 [ - + ]: 93 : if (anycompatible_range_typelem != anycompatible_typeid)
1487 tgl@sss.pgh.pa.us 2585 [ # # ]:UBC 0 : ereport(ERROR,
2586 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2587 : : errmsg("anycompatiblerange type %s does not match anycompatible type %s",
2588 : : format_type_be(anycompatible_range_typeid),
2589 : : format_type_be(anycompatible_typeid))));
2590 : : }
2591 : :
992 tgl@sss.pgh.pa.us 2592 [ + + ]:CBC 1785 : if (have_anycompatible_multirange)
2593 : : {
2594 : : /* we can't infer a multirange type from the others */
2595 [ + + ]: 42 : if (!OidIsValid(anycompatible_multirange_typeid))
2596 [ + - ]: 3 : ereport(ERROR,
2597 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2598 : : errmsg("could not determine polymorphic type %s because input has type %s",
2599 : : "anycompatiblemultirange", "unknown")));
2600 : :
2601 : : /*
2602 : : * the anycompatible type must exactly match the multirange
2603 : : * element type
2604 : : */
2605 [ - + ]: 39 : if (anycompatible_range_typelem != anycompatible_typeid)
992 tgl@sss.pgh.pa.us 2606 [ # # ]:UBC 0 : ereport(ERROR,
2607 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2608 : : errmsg("anycompatiblemultirange type %s does not match anycompatible type %s",
2609 : : format_type_be(anycompatible_multirange_typeid),
2610 : : format_type_be(anycompatible_typeid))));
2611 : : }
2612 : :
1487 tgl@sss.pgh.pa.us 2613 [ + + ]:CBC 1782 : if (have_anycompatible_nonarray)
2614 : : {
2615 : : /*
2616 : : * require the element type to not be an array or domain over
2617 : : * array
2618 : : */
2619 [ - + ]: 6 : if (type_is_array_domain(anycompatible_typeid))
1487 tgl@sss.pgh.pa.us 2620 [ # # ]:UBC 0 : ereport(ERROR,
2621 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2622 : : errmsg("type matched to anycompatiblenonarray is an array type: %s",
2623 : : format_type_be(anycompatible_typeid))));
2624 : : }
2625 : : }
2626 : : else
2627 : : {
1487 tgl@sss.pgh.pa.us 2628 [ + + ]:CBC 16 : if (allow_poly)
2629 : : {
2630 : 4 : anycompatible_typeid = ANYCOMPATIBLEOID;
2631 : 4 : anycompatible_array_typeid = ANYCOMPATIBLEARRAYOID;
2632 : 4 : anycompatible_range_typeid = ANYCOMPATIBLERANGEOID;
1211 akorotkov@postgresql 2633 : 4 : anycompatible_multirange_typeid = ANYCOMPATIBLEMULTIRANGEOID;
2634 : : }
2635 : : else
2636 : : {
2637 : : /*
2638 : : * Only way to get here is if all the family-2 polymorphic
2639 : : * arguments have UNKNOWN inputs. Resolve to TEXT as
2640 : : * select_common_type() would do. That doesn't license us to
2641 : : * use TEXTRANGE or TEXTMULTIRANGE, though.
2642 : : */
1487 tgl@sss.pgh.pa.us 2643 : 12 : anycompatible_typeid = TEXTOID;
2644 : 12 : anycompatible_array_typeid = TEXTARRAYOID;
2645 [ + + ]: 12 : if (have_anycompatible_range)
2646 [ + - ]: 6 : ereport(ERROR,
2647 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2648 : : errmsg("could not determine polymorphic type %s because input has type %s",
2649 : : "anycompatiblerange", "unknown")));
992 2650 [ + + ]: 6 : if (have_anycompatible_multirange)
2651 [ + - ]: 3 : ereport(ERROR,
2652 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2653 : : errmsg("could not determine polymorphic type %s because input has type %s",
2654 : : "anycompatiblemultirange", "unknown")));
2655 : : }
2656 : : }
2657 : :
2658 : : /* replace family-2 polymorphic types by selected types */
1487 2659 [ + + ]: 5424 : for (int j = 0; j < nargs; j++)
2660 : : {
2661 : 3635 : Oid decl_type = declared_arg_types[j];
2662 : :
2663 [ + + + + ]: 3635 : if (decl_type == ANYCOMPATIBLEOID ||
2664 : : decl_type == ANYCOMPATIBLENONARRAYOID)
2665 : 1047 : declared_arg_types[j] = anycompatible_typeid;
2666 [ + + ]: 2588 : else if (decl_type == ANYCOMPATIBLEARRAYOID)
2667 : 2417 : declared_arg_types[j] = anycompatible_array_typeid;
2668 [ + + ]: 171 : else if (decl_type == ANYCOMPATIBLERANGEOID)
2669 : 63 : declared_arg_types[j] = anycompatible_range_typeid;
1211 akorotkov@postgresql 2670 [ + + ]: 108 : else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
2671 : 39 : declared_arg_types[j] = anycompatible_multirange_typeid;
2672 : : }
2673 : : }
2674 : :
2675 : : /*
2676 : : * If we had any UNKNOWN inputs for family-1 polymorphic arguments,
2677 : : * re-scan to assign correct types to them.
2678 : : *
2679 : : * Note: we don't have to consider unknown inputs that were matched to
2680 : : * family-2 polymorphic arguments, because we forcibly updated their
2681 : : * declared_arg_types[] positions just above.
2682 : : */
1489 tgl@sss.pgh.pa.us 2683 [ + + ]: 28326 : if (have_poly_unknowns)
2684 : : {
2685 [ + + ]: 8518 : for (int j = 0; j < nargs; j++)
2686 : : {
6157 2687 : 5825 : Oid decl_type = declared_arg_types[j];
7559 bruce@momjian.us 2688 : 5825 : Oid actual_type = actual_arg_types[j];
2689 : :
7677 tgl@sss.pgh.pa.us 2690 [ + + ]: 5825 : if (actual_type != UNKNOWNOID)
2691 : 2807 : continue;
2692 : :
6157 2693 [ + + + + ]: 3018 : if (decl_type == ANYELEMENTOID ||
2694 [ + + ]: 2749 : decl_type == ANYNONARRAYOID ||
2695 : : decl_type == ANYENUMOID)
7677 2696 : 357 : declared_arg_types[j] = elem_typeid;
6157 2697 [ + + ]: 2661 : else if (decl_type == ANYARRAYOID)
2698 : : {
7677 2699 [ + + ]: 1980 : if (!OidIsValid(array_typeid))
2700 : : {
2701 : 9 : array_typeid = get_array_type(elem_typeid);
2702 [ - + ]: 9 : if (!OidIsValid(array_typeid))
7575 tgl@sss.pgh.pa.us 2703 [ # # ]:UBC 0 : ereport(ERROR,
2704 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
2705 : : errmsg("could not find array type for data type %s",
2706 : : format_type_be(elem_typeid))));
2707 : : }
7677 tgl@sss.pgh.pa.us 2708 :CBC 1980 : declared_arg_types[j] = array_typeid;
2709 : : }
4546 heikki.linnakangas@i 2710 [ + + ]: 681 : else if (decl_type == ANYRANGEOID)
2711 : : {
2712 [ - + ]: 233 : if (!OidIsValid(range_typeid))
2713 : : {
2714 : : /* we can't infer a range type from the others */
4546 heikki.linnakangas@i 2715 [ # # ]:UBC 0 : ereport(ERROR,
2716 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2717 : : errmsg("could not determine polymorphic type %s because input has type %s",
2718 : : "anyrange", "unknown")));
2719 : : }
4546 heikki.linnakangas@i 2720 :CBC 233 : declared_arg_types[j] = range_typeid;
2721 : : }
1211 akorotkov@postgresql 2722 [ + + ]: 448 : else if (decl_type == ANYMULTIRANGEOID)
2723 : : {
2724 [ - + ]: 126 : if (!OidIsValid(multirange_typeid))
2725 : : {
2726 : : /* we can't infer a multirange type from the others */
1211 akorotkov@postgresql 2727 [ # # ]:UBC 0 : ereport(ERROR,
2728 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2729 : : errmsg("could not determine polymorphic type %s because input has type %s",
2730 : : "anymultirange", "unknown")));
2731 : : }
1211 akorotkov@postgresql 2732 :CBC 126 : declared_arg_types[j] = multirange_typeid;
2733 : : }
2734 : : }
2735 : : }
2736 : :
2737 : : /* if we return ANYELEMENT use the appropriate argument type */
1489 tgl@sss.pgh.pa.us 2738 [ + + + - ]: 28326 : if (rettype == ANYELEMENTOID ||
2739 [ + + ]: 23397 : rettype == ANYNONARRAYOID ||
2740 : : rettype == ANYENUMOID)
2741 : 5043 : return elem_typeid;
2742 : :
2743 : : /* if we return ANYARRAY use the appropriate argument type */
7677 2744 [ + + ]: 23283 : if (rettype == ANYARRAYOID)
2745 : : {
2746 [ + + ]: 7741 : if (!OidIsValid(array_typeid))
2747 : : {
7599 bruce@momjian.us 2748 : 7257 : array_typeid = get_array_type(elem_typeid);
7677 tgl@sss.pgh.pa.us 2749 [ - + ]: 7257 : if (!OidIsValid(array_typeid))
7575 tgl@sss.pgh.pa.us 2750 [ # # ]:UBC 0 : ereport(ERROR,
2751 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
2752 : : errmsg("could not find array type for data type %s",
2753 : : format_type_be(elem_typeid))));
2754 : : }
7677 tgl@sss.pgh.pa.us 2755 :CBC 7741 : return array_typeid;
2756 : : }
2757 : :
2758 : : /* if we return ANYRANGE use the appropriate argument type */
4546 heikki.linnakangas@i 2759 [ + + ]: 15542 : if (rettype == ANYRANGEOID)
2760 : : {
2761 : : /* this error is unreachable if the function signature is valid: */
2762 [ - + ]: 94 : if (!OidIsValid(range_typeid))
4546 heikki.linnakangas@i 2763 [ # # ]:UBC 0 : ereport(ERROR,
2764 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2765 : : errmsg_internal("could not determine polymorphic type %s because input has type %s",
2766 : : "anyrange", "unknown")));
4546 heikki.linnakangas@i 2767 :CBC 94 : return range_typeid;
2768 : : }
2769 : :
2770 : : /* if we return ANYMULTIRANGE use the appropriate argument type */
1211 akorotkov@postgresql 2771 [ + + ]: 15448 : if (rettype == ANYMULTIRANGEOID)
2772 : : {
2773 : : /* this error is unreachable if the function signature is valid: */
2774 [ - + ]: 406 : if (!OidIsValid(multirange_typeid))
992 tgl@sss.pgh.pa.us 2775 [ # # ]:UBC 0 : ereport(ERROR,
2776 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2777 : : errmsg_internal("could not determine polymorphic type %s because input has type %s",
2778 : : "anymultirange", "unknown")));
1211 akorotkov@postgresql 2779 :CBC 406 : return multirange_typeid;
2780 : : }
2781 : :
2782 : : /* if we return ANYCOMPATIBLE use the appropriate type */
1487 tgl@sss.pgh.pa.us 2783 [ + + - + ]: 15042 : if (rettype == ANYCOMPATIBLEOID ||
2784 : : rettype == ANYCOMPATIBLENONARRAYOID)
2785 : : {
2786 : : /* this error is unreachable if the function signature is valid: */
2787 [ - + ]: 79 : if (!OidIsValid(anycompatible_typeid))
1487 tgl@sss.pgh.pa.us 2788 [ # # ]:UBC 0 : ereport(ERROR,
2789 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2790 : : errmsg_internal("could not identify anycompatible type")));
1487 tgl@sss.pgh.pa.us 2791 :CBC 79 : return anycompatible_typeid;
2792 : : }
2793 : :
2794 : : /* if we return ANYCOMPATIBLEARRAY use the appropriate type */
2795 [ + + ]: 14963 : if (rettype == ANYCOMPATIBLEARRAYOID)
2796 : : {
2797 : : /* this error is unreachable if the function signature is valid: */
2798 [ - + ]: 1521 : if (!OidIsValid(anycompatible_array_typeid))
1487 tgl@sss.pgh.pa.us 2799 [ # # ]:UBC 0 : ereport(ERROR,
2800 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2801 : : errmsg_internal("could not identify anycompatiblearray type")));
1487 tgl@sss.pgh.pa.us 2802 :CBC 1521 : return anycompatible_array_typeid;
2803 : : }
2804 : :
2805 : : /* if we return ANYCOMPATIBLERANGE use the appropriate argument type */
2806 [ + + ]: 13442 : if (rettype == ANYCOMPATIBLERANGEOID)
2807 : : {
2808 : : /* this error is unreachable if the function signature is valid: */
2809 [ - + ]: 21 : if (!OidIsValid(anycompatible_range_typeid))
1487 tgl@sss.pgh.pa.us 2810 [ # # ]:UBC 0 : ereport(ERROR,
2811 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2812 : : errmsg_internal("could not identify anycompatiblerange type")));
1487 tgl@sss.pgh.pa.us 2813 :CBC 21 : return anycompatible_range_typeid;
2814 : : }
2815 : :
2816 : : /* if we return ANYCOMPATIBLEMULTIRANGE use the appropriate argument type */
1211 akorotkov@postgresql 2817 [ + + ]: 13421 : if (rettype == ANYCOMPATIBLEMULTIRANGEOID)
2818 : : {
2819 : : /* this error is unreachable if the function signature is valid: */
2820 [ - + ]: 15 : if (!OidIsValid(anycompatible_multirange_typeid))
1211 akorotkov@postgresql 2821 [ # # ]:UBC 0 : ereport(ERROR,
2822 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2823 : : errmsg_internal("could not identify anycompatiblemultirange type")));
1211 akorotkov@postgresql 2824 :CBC 15 : return anycompatible_multirange_typeid;
2825 : : }
2826 : :
2827 : : /* we don't return a generic type; send back the original return type */
7677 tgl@sss.pgh.pa.us 2828 : 13406 : return rettype;
2829 : : }
2830 : :
2831 : : /*
2832 : : * check_valid_polymorphic_signature()
2833 : : * Is a proposed function signature valid per polymorphism rules?
2834 : : *
2835 : : * Returns NULL if the signature is valid (either ret_type is not polymorphic,
2836 : : * or it can be deduced from the given declared argument types). Otherwise,
2837 : : * returns a palloc'd, already translated errdetail string saying why not.
2838 : : */
2839 : : char *
1489 2840 : 16491 : check_valid_polymorphic_signature(Oid ret_type,
2841 : : const Oid *declared_arg_types,
2842 : : int nargs)
2843 : : {
1211 akorotkov@postgresql 2844 [ + + + + ]: 16491 : if (ret_type == ANYRANGEOID || ret_type == ANYMULTIRANGEOID)
2845 : : {
2846 : : /*
2847 : : * ANYRANGE and ANYMULTIRANGE require an ANYRANGE or ANYMULTIRANGE
2848 : : * input, else we can't tell which of several range types with the
2849 : : * same element type to use.
2850 : : */
1489 tgl@sss.pgh.pa.us 2851 [ + + ]: 114 : for (int i = 0; i < nargs; i++)
2852 : : {
1211 akorotkov@postgresql 2853 [ + + ]: 78 : if (declared_arg_types[i] == ANYRANGEOID ||
2854 [ + + ]: 59 : declared_arg_types[i] == ANYMULTIRANGEOID)
1489 tgl@sss.pgh.pa.us 2855 : 38 : return NULL; /* OK */
2856 : : }
1211 akorotkov@postgresql 2857 : 36 : return psprintf(_("A result of type %s requires at least one input of type anyrange or anymultirange."),
2858 : : format_type_be(ret_type));
2859 : : }
2860 [ + + + + ]: 16417 : else if (ret_type == ANYCOMPATIBLERANGEOID || ret_type == ANYCOMPATIBLEMULTIRANGEOID)
2861 : : {
2862 : : /*
2863 : : * ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE require an
2864 : : * ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE input, else we can't
2865 : : * tell which of several range types with the same element type to
2866 : : * use.
2867 : : */
2868 [ + + ]: 72 : for (int i = 0; i < nargs; i++)
2869 : : {
2870 [ + + ]: 51 : if (declared_arg_types[i] == ANYCOMPATIBLERANGEOID ||
2871 [ + + ]: 36 : declared_arg_types[i] == ANYCOMPATIBLEMULTIRANGEOID)
2872 : 24 : return NULL; /* OK */
2873 : : }
2874 : 21 : return psprintf(_("A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange."),
2875 : : format_type_be(ret_type));
2876 : : }
1487 tgl@sss.pgh.pa.us 2877 [ + + + + : 16372 : else if (IsPolymorphicTypeFamily1(ret_type))
+ - + - +
- - + ]
2878 : : {
2879 : : /* Otherwise, any family-1 type can be deduced from any other */
1489 2880 [ + + ]: 578 : for (int i = 0; i < nargs; i++)
2881 : : {
1487 2882 [ + + + + : 521 : if (IsPolymorphicTypeFamily1(declared_arg_types[i]))
+ - + - +
+ + + ]
1489 2883 : 470 : return NULL; /* OK */
2884 : : }
2885 : : /* Keep this list in sync with IsPolymorphicTypeFamily1! */
1211 akorotkov@postgresql 2886 : 57 : return psprintf(_("A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange."),
2887 : : format_type_be(ret_type));
2888 : : }
1487 tgl@sss.pgh.pa.us 2889 [ + + + + : 15845 : else if (IsPolymorphicTypeFamily2(ret_type))
+ - + - -
+ ]
2890 : : {
2891 : : /* Otherwise, any family-2 type can be deduced from any other */
2892 [ + + ]: 118 : for (int i = 0; i < nargs; i++)
2893 : : {
2894 [ + + + + : 115 : if (IsPolymorphicTypeFamily2(declared_arg_types[i]))
+ + + + +
+ ]
2895 : 94 : return NULL; /* OK */
2896 : : }
2897 : : /* Keep this list in sync with IsPolymorphicTypeFamily2! */
992 2898 : 3 : return psprintf(_("A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange."),
2899 : : format_type_be(ret_type));
2900 : : }
2901 : : else
1489 2902 : 15748 : return NULL; /* OK, ret_type is not polymorphic */
2903 : : }
2904 : :
2905 : : /*
2906 : : * check_valid_internal_signature()
2907 : : * Is a proposed function signature valid per INTERNAL safety rules?
2908 : : *
2909 : : * Returns NULL if OK, or a suitable error message if ret_type is INTERNAL but
2910 : : * none of the declared arg types are. (It's unsafe to create such a function
2911 : : * since it would allow invocation of INTERNAL-consuming functions directly
2912 : : * from SQL.) It's overkill to return the error detail message, since there
2913 : : * is only one possibility, but we do it like this to keep the API similar to
2914 : : * check_valid_polymorphic_signature().
2915 : : */
2916 : : char *
2917 : 15964 : check_valid_internal_signature(Oid ret_type,
2918 : : const Oid *declared_arg_types,
2919 : : int nargs)
2920 : : {
2921 [ + + ]: 15964 : if (ret_type == INTERNALOID)
2922 : : {
2923 [ + - ]: 531 : for (int i = 0; i < nargs; i++)
2924 : : {
2925 [ + + ]: 531 : if (declared_arg_types[i] == ret_type)
2926 : 378 : return NULL; /* OK */
2927 : : }
1489 tgl@sss.pgh.pa.us 2928 :UBC 0 : return pstrdup(_("A result of type internal requires at least one input of type internal."));
2929 : : }
2930 : : else
1489 tgl@sss.pgh.pa.us 2931 :CBC 15586 : return NULL; /* OK, ret_type is not INTERNAL */
2932 : : }
2933 : :
2934 : :
2935 : : /* TypeCategory()
2936 : : * Assign a category to the specified type OID.
2937 : : *
2938 : : * NB: this must not return TYPCATEGORY_INVALID.
2939 : : */
2940 : : TYPCATEGORY
5737 2941 : 81472 : TypeCategory(Oid type)
2942 : : {
2943 : : char typcategory;
2944 : : bool typispreferred;
2945 : :
2946 : 81472 : get_type_category_preferred(type, &typcategory, &typispreferred);
2947 [ - + ]: 81472 : Assert(typcategory != TYPCATEGORY_INVALID);
2948 : 81472 : return (TYPCATEGORY) typcategory;
2949 : : }
2950 : :
2951 : :
2952 : : /* IsPreferredType()
2953 : : * Check if this type is a preferred type for the given category.
2954 : : *
2955 : : * If category is TYPCATEGORY_INVALID, then we'll return true for preferred
2956 : : * types of any category; otherwise, only for preferred types of that
2957 : : * category.
2958 : : */
2959 : : bool
2960 : 13936 : IsPreferredType(TYPCATEGORY category, Oid type)
2961 : : {
2962 : : char typcategory;
2963 : : bool typispreferred;
2964 : :
2965 : 13936 : get_type_category_preferred(type, &typcategory, &typispreferred);
2966 [ + + - + ]: 13936 : if (category == typcategory || category == TYPCATEGORY_INVALID)
2967 : 9414 : return typispreferred;
2968 : : else
7629 2969 : 4522 : return false;
2970 : : }
2971 : :
2972 : :
2973 : : /* IsBinaryCoercible()
2974 : : * Check if srctype is binary-coercible to targettype.
2975 : : *
2976 : : * This notion allows us to cheat and directly exchange values without
2977 : : * going through the trouble of calling a conversion function. Note that
2978 : : * in general, this should only be an implementation shortcut. Before 7.4,
2979 : : * this was also used as a heuristic for resolving overloaded functions and
2980 : : * operators, but that's basically a bad idea.
2981 : : *
2982 : : * As of 7.3, binary coercibility isn't hardwired into the code anymore.
2983 : : * We consider two types binary-coercible if there is an implicitly
2984 : : * invokable, no-function-needed pg_cast entry. Also, a domain is always
2985 : : * binary-coercible to its base type, though *not* vice versa (in the other
2986 : : * direction, one must apply domain constraint checks before accepting the
2987 : : * value as legitimate). We also need to special-case various polymorphic
2988 : : * types.
2989 : : *
2990 : : * This function replaces IsBinaryCompatible(), which was an inherently
2991 : : * symmetric test. Since the pg_cast entries aren't necessarily symmetric,
2992 : : * the order of the operands is now significant.
2993 : : */
2994 : : bool
7879 2995 : 1096260 : IsBinaryCoercible(Oid srctype, Oid targettype)
2996 : : {
2997 : : Oid castoid;
2998 : :
545 2999 : 1096260 : return IsBinaryCoercibleWithCast(srctype, targettype, &castoid);
3000 : : }
3001 : :
3002 : : /* IsBinaryCoercibleWithCast()
3003 : : * Check if srctype is binary-coercible to targettype.
3004 : : *
3005 : : * This variant also returns the OID of the pg_cast entry if one is involved.
3006 : : * *castoid is set to InvalidOid if no binary-coercible cast exists, or if
3007 : : * there is a hard-wired rule for it rather than a pg_cast entry.
3008 : : */
3009 : : bool
3010 : 1096356 : IsBinaryCoercibleWithCast(Oid srctype, Oid targettype,
3011 : : Oid *castoid)
3012 : : {
3013 : : HeapTuple tuple;
3014 : : Form_pg_cast castForm;
3015 : : bool result;
3016 : :
3017 : 1096356 : *castoid = InvalidOid;
3018 : :
3019 : : /* Fast path if same type */
7879 3020 [ + + ]: 1096356 : if (srctype == targettype)
7896 3021 : 248176 : return true;
3022 : :
3023 : : /* Anything is coercible to ANY or ANYELEMENT or ANYCOMPATIBLE */
1487 3024 [ + + + + : 848180 : if (targettype == ANYOID || targettype == ANYELEMENTOID ||
- + ]
3025 : : targettype == ANYCOMPATIBLEOID)
3765 3026 : 94 : return true;
3027 : :
3028 : : /* If srctype is a domain, reduce to its base type */
7879 3029 [ + - ]: 848086 : if (OidIsValid(srctype))
3030 : 848086 : srctype = getBaseType(srctype);
3031 : :
3032 : : /* Somewhat-fast path for domain -> base type case */
3033 [ + + ]: 848086 : if (srctype == targettype)
7896 3034 : 6 : return true;
3035 : :
3036 : : /* Also accept any array type as coercible to ANY[COMPATIBLE]ARRAY */
1487 3037 [ + + - + ]: 848080 : if (targettype == ANYARRAYOID || targettype == ANYCOMPATIBLEARRAYOID)
4529 3038 [ + + ]: 45234 : if (type_is_array(srctype))
6157 3039 : 2004 : return true;
3040 : :
3041 : : /* Also accept any non-array type as coercible to ANY[COMPATIBLE]NONARRAY */
1487 3042 [ + - - + ]: 846076 : if (targettype == ANYNONARRAYOID || targettype == ANYCOMPATIBLENONARRAYOID)
4529 tgl@sss.pgh.pa.us 3043 [ # # ]:UBC 0 : if (!type_is_array(srctype))
7597 3044 : 0 : return true;
3045 : :
3046 : : /* Also accept any enum type as coercible to ANYENUM */
6222 tgl@sss.pgh.pa.us 3047 [ + + ]:CBC 846076 : if (targettype == ANYENUMOID)
3048 [ + + ]: 41988 : if (type_is_enum(srctype))
3049 : 80 : return true;
3050 : :
3051 : : /* Also accept any range type as coercible to ANY[COMPATIBLE]RANGE */
1487 3052 [ + + - + ]: 845996 : if (targettype == ANYRANGEOID || targettype == ANYCOMPATIBLERANGEOID)
4546 heikki.linnakangas@i 3053 [ + + ]: 11045 : if (type_is_range(srctype))
3054 : 1464 : return true;
3055 : :
3056 : : /* Also, any multirange type is coercible to ANY[COMPATIBLE]MULTIRANGE */
1211 akorotkov@postgresql 3057 [ + + - + ]: 844532 : if (targettype == ANYMULTIRANGEOID || targettype == ANYCOMPATIBLEMULTIRANGEOID)
3058 [ + + ]: 23482 : if (type_is_multirange(srctype))
3059 : 126 : return true;
3060 : :
3061 : : /* Also accept any composite type as coercible to RECORD */
5662 tgl@sss.pgh.pa.us 3062 [ + + ]: 844406 : if (targettype == RECORDOID)
3063 [ + + ]: 9382 : if (ISCOMPLEX(srctype))
3064 : 382 : return true;
3065 : :
3066 : : /* Also accept any composite array type as coercible to RECORD[] */
3067 [ - + ]: 844024 : if (targettype == RECORDARRAYOID)
5662 tgl@sss.pgh.pa.us 3068 [ # # ]:UBC 0 : if (is_complex_array(srctype))
3069 : 0 : return true;
3070 : :
3071 : : /* Else look in pg_cast */
5173 rhaas@postgresql.org 3072 :CBC 844024 : tuple = SearchSysCache2(CASTSOURCETARGET,
3073 : : ObjectIdGetDatum(srctype),
3074 : : ObjectIdGetDatum(targettype));
7896 tgl@sss.pgh.pa.us 3075 [ + + ]: 844024 : if (!HeapTupleIsValid(tuple))
3076 : 693025 : return false; /* no cast */
3077 : 150999 : castForm = (Form_pg_cast) GETSTRUCT(tuple);
3078 : :
5155 heikki.linnakangas@i 3079 [ + + ]: 167624 : result = (castForm->castmethod == COERCION_METHOD_BINARY &&
7879 tgl@sss.pgh.pa.us 3080 [ + + ]: 16625 : castForm->castcontext == COERCION_CODE_IMPLICIT);
3081 : :
545 3082 [ + + ]: 150999 : if (result)
3083 : 7009 : *castoid = castForm->oid;
3084 : :
7896 3085 : 150999 : ReleaseSysCache(tuple);
3086 : :
3087 : 150999 : return result;
3088 : : }
3089 : :
3090 : :
3091 : : /*
3092 : : * find_coercion_pathway
3093 : : * Look for a coercion pathway between two types.
3094 : : *
3095 : : * Currently, this deals only with scalar-type cases; it does not consider
3096 : : * polymorphic types nor casts between composite types. (Perhaps fold
3097 : : * those in someday?)
3098 : : *
3099 : : * ccontext determines the set of available casts.
3100 : : *
3101 : : * The possible result codes are:
3102 : : * COERCION_PATH_NONE: failed to find any coercion pathway
3103 : : * *funcid is set to InvalidOid
3104 : : * COERCION_PATH_FUNC: apply the coercion function returned in *funcid
3105 : : * COERCION_PATH_RELABELTYPE: binary-compatible cast, no function needed
3106 : : * *funcid is set to InvalidOid
3107 : : * COERCION_PATH_ARRAYCOERCE: need an ArrayCoerceExpr node
3108 : : * *funcid is set to InvalidOid
3109 : : * COERCION_PATH_COERCEVIAIO: need a CoerceViaIO node
3110 : : * *funcid is set to InvalidOid
3111 : : *
3112 : : * Note: COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
3113 : : * needed to do the coercion; if the target is a domain then we may need to
3114 : : * apply domain constraint checking. If you want to check for a zero-effort
3115 : : * conversion then use IsBinaryCoercible().
3116 : : */
3117 : : CoercionPathType
7879 3118 : 573346 : find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
3119 : : CoercionContext ccontext,
3120 : : Oid *funcid)
3121 : : {
6158 3122 : 573346 : CoercionPathType result = COERCION_PATH_NONE;
3123 : : HeapTuple tuple;
3124 : :
7896 3125 : 573346 : *funcid = InvalidOid;
3126 : :
3127 : : /* Perhaps the types are domains; if so, look at their base types */
3128 [ + - ]: 573346 : if (OidIsValid(sourceTypeId))
3129 : 573346 : sourceTypeId = getBaseType(sourceTypeId);
3130 [ + - ]: 573346 : if (OidIsValid(targetTypeId))
3131 : 573346 : targetTypeId = getBaseType(targetTypeId);
3132 : :
3133 : : /* Domains are always coercible to and from their base type */
3134 [ + + ]: 573346 : if (sourceTypeId == targetTypeId)
6158 3135 : 36975 : return COERCION_PATH_RELABELTYPE;
3136 : :
3137 : : /* Look in pg_cast */
5173 rhaas@postgresql.org 3138 : 536371 : tuple = SearchSysCache2(CASTSOURCETARGET,
3139 : : ObjectIdGetDatum(sourceTypeId),
3140 : : ObjectIdGetDatum(targetTypeId));
3141 : :
7941 peter_e@gmx.net 3142 [ + + ]: 536371 : if (HeapTupleIsValid(tuple))
3143 : : {
7896 tgl@sss.pgh.pa.us 3144 : 205687 : Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
3145 : : CoercionContext castcontext;
3146 : :
3147 : : /* convert char value for castcontext to CoercionContext enum */
7879 3148 [ + + + - ]: 205687 : switch (castForm->castcontext)
3149 : : {
3150 : 162779 : case COERCION_CODE_IMPLICIT:
3151 : 162779 : castcontext = COERCION_IMPLICIT;
3152 : 162779 : break;
3153 : 38901 : case COERCION_CODE_ASSIGNMENT:
3154 : 38901 : castcontext = COERCION_ASSIGNMENT;
3155 : 38901 : break;
3156 : 4007 : case COERCION_CODE_EXPLICIT:
3157 : 4007 : castcontext = COERCION_EXPLICIT;
3158 : 4007 : break;
7879 tgl@sss.pgh.pa.us 3159 :UBC 0 : default:
7575 3160 [ # # ]: 0 : elog(ERROR, "unrecognized castcontext: %d",
3161 : : (int) castForm->castcontext);
3162 : : castcontext = 0; /* keep compiler quiet */
3163 : : break;
3164 : : }
3165 : :
3166 : : /* Rely on ordering of enum for correct behavior here */
7879 tgl@sss.pgh.pa.us 3167 [ + + ]:CBC 205687 : if (ccontext >= castcontext)
3168 : : {
5644 heikki.linnakangas@i 3169 [ + + + - ]: 172181 : switch (castForm->castmethod)
3170 : : {
3171 : 69535 : case COERCION_METHOD_FUNCTION:
3172 : 69535 : result = COERCION_PATH_FUNC;
3173 : 69535 : *funcid = castForm->castfunc;
3174 : 69535 : break;
3175 : 364 : case COERCION_METHOD_INOUT:
3176 : 364 : result = COERCION_PATH_COERCEVIAIO;
3177 : 364 : break;
3178 : 102282 : case COERCION_METHOD_BINARY:
3179 : 102282 : result = COERCION_PATH_RELABELTYPE;
3180 : 102282 : break;
5644 heikki.linnakangas@i 3181 :UBC 0 : default:
3182 [ # # ]: 0 : elog(ERROR, "unrecognized castmethod: %d",
3183 : : (int) castForm->castmethod);
3184 : : break;
3185 : : }
3186 : : }
3187 : :
7941 peter_e@gmx.net 3188 :CBC 205687 : ReleaseSysCache(tuple);
3189 : : }
3190 : : else
3191 : : {
3192 : : /*
3193 : : * If there's no pg_cast entry, perhaps we are dealing with a pair of
3194 : : * array types. If so, and if their element types have a conversion
3195 : : * pathway, report that we can coerce with an ArrayCoerceExpr.
3196 : : *
3197 : : * Hack: disallow coercions to oidvector and int2vector, which
3198 : : * otherwise tend to capture coercions that should go to "real" array
3199 : : * types. We want those types to be considered "real" arrays for many
3200 : : * purposes, but not this one. (Also, ArrayCoerceExpr isn't
3201 : : * guaranteed to produce an output that meets the restrictions of
3202 : : * these datatypes, such as being 1-dimensional.)
3203 : : */
6158 tgl@sss.pgh.pa.us 3204 [ + + + - ]: 330684 : if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
3205 : : {
3206 : : Oid targetElem;
3207 : : Oid sourceElem;
3208 : :
3209 [ + + + + ]: 330777 : if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
2388 3210 : 5139 : (sourceElem = get_element_type(sourceTypeId)) != InvalidOid)
3211 : : {
3212 : : CoercionPathType elempathtype;
3213 : : Oid elemfuncid;
3214 : :
6158 3215 : 4571 : elempathtype = find_coercion_pathway(targetElem,
3216 : : sourceElem,
3217 : : ccontext,
3218 : : &elemfuncid);
2388 3219 [ + + ]: 4571 : if (elempathtype != COERCION_PATH_NONE)
3220 : : {
3221 : 4335 : result = COERCION_PATH_ARRAYCOERCE;
3222 : : }
3223 : : }
3224 : : }
3225 : :
3226 : : /*
3227 : : * If we still haven't found a possibility, consider automatic casting
3228 : : * using I/O functions. We allow assignment casts to string types and
3229 : : * explicit casts from string types to be handled this way. (The
3230 : : * CoerceViaIO mechanism is a lot more general than that, but this is
3231 : : * all we want to allow in the absence of a pg_cast entry.) It would
3232 : : * probably be better to insist on explicit casts in both directions,
3233 : : * but this is a compromise to preserve something of the pre-8.3
3234 : : * behavior that many types had implicit (yipes!) casts to text.
3235 : : */
6158 3236 [ + + ]: 330684 : if (result == COERCION_PATH_NONE)
3237 : : {
3238 [ + + + + ]: 348949 : if (ccontext >= COERCION_ASSIGNMENT &&
5737 3239 : 22600 : TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
6158 3240 : 17823 : result = COERCION_PATH_COERCEVIAIO;
3241 [ + + + + ]: 312842 : else if (ccontext >= COERCION_EXPLICIT &&
5737 3242 : 4316 : TypeCategory(sourceTypeId) == TYPCATEGORY_STRING)
6158 3243 : 2586 : result = COERCION_PATH_COERCEVIAIO;
3244 : : }
3245 : : }
3246 : :
3247 : : /*
3248 : : * When parsing PL/pgSQL assignments, allow an I/O cast to be used
3249 : : * whenever no normal coercion is available.
3250 : : */
1196 3251 [ + + + + ]: 536371 : if (result == COERCION_PATH_NONE &&
3252 : : ccontext == COERCION_PLPGSQL)
3253 : 110 : result = COERCION_PATH_COERCEVIAIO;
3254 : :
7896 3255 : 536371 : return result;
3256 : : }
3257 : :
3258 : :
3259 : : /*
3260 : : * find_typmod_coercion_function -- does the given type need length coercion?
3261 : : *
3262 : : * If the target type possesses a pg_cast function from itself to itself,
3263 : : * it must need length coercion.
3264 : : *
3265 : : * "bpchar" (ie, char(N)) and "numeric" are examples of such types.
3266 : : *
3267 : : * If the given type is a varlena array type, we do not look for a coercion
3268 : : * function associated directly with the array type, but instead look for
3269 : : * one associated with the element type. An ArrayCoerceExpr node must be
3270 : : * used to apply such a function. (Note: currently, it's pointless to
3271 : : * return the funcid in this case, because it'll just get looked up again
3272 : : * in the recursive construction of the ArrayCoerceExpr's elemexpr.)
3273 : : *
3274 : : * We use the same result enum as find_coercion_pathway, but the only possible
3275 : : * result codes are:
3276 : : * COERCION_PATH_NONE: no length coercion needed
3277 : : * COERCION_PATH_FUNC: apply the function returned in *funcid
3278 : : * COERCION_PATH_ARRAYCOERCE: apply the function using ArrayCoerceExpr
3279 : : */
3280 : : CoercionPathType
6228 3281 : 10033 : find_typmod_coercion_function(Oid typeId,
3282 : : Oid *funcid)
3283 : : {
3284 : : CoercionPathType result;
3285 : : Type targetType;
3286 : : Form_pg_type typeForm;
3287 : : HeapTuple tuple;
3288 : :
3289 : 10033 : *funcid = InvalidOid;
6158 3290 : 10033 : result = COERCION_PATH_FUNC;
3291 : :
7941 peter_e@gmx.net 3292 : 10033 : targetType = typeidType(typeId);
7879 tgl@sss.pgh.pa.us 3293 : 10033 : typeForm = (Form_pg_type) GETSTRUCT(targetType);
3294 : :
3295 : : /* Check for a "true" array type */
1222 3296 [ + + + - ]: 10033 : if (IsTrueArrayType(typeForm))
3297 : : {
3298 : : /* Yes, switch our attention to the element type */
7879 3299 : 42 : typeId = typeForm->typelem;
6158 3300 : 42 : result = COERCION_PATH_ARRAYCOERCE;
3301 : : }
7242 3302 : 10033 : ReleaseSysCache(targetType);
3303 : :
3304 : : /* Look in pg_cast */
5173 rhaas@postgresql.org 3305 : 10033 : tuple = SearchSysCache2(CASTSOURCETARGET,
3306 : : ObjectIdGetDatum(typeId),
3307 : : ObjectIdGetDatum(typeId));
3308 : :
7242 tgl@sss.pgh.pa.us 3309 [ + + ]: 10033 : if (HeapTupleIsValid(tuple))
3310 : : {
3311 : 10027 : Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
3312 : :
6228 3313 : 10027 : *funcid = castForm->castfunc;
7242 3314 : 10027 : ReleaseSysCache(tuple);
3315 : : }
3316 : :
6158 3317 [ + + ]: 10033 : if (!OidIsValid(*funcid))
3318 : 6 : result = COERCION_PATH_NONE;
3319 : :
3320 : 10033 : return result;
3321 : : }
3322 : :
3323 : : /*
3324 : : * is_complex_array
3325 : : * Is this type an array of composite?
3326 : : *
3327 : : * Note: this will not return true for record[]; check for RECORDARRAYOID
3328 : : * separately if needed.
3329 : : */
3330 : : static bool
5662 3331 : 14 : is_complex_array(Oid typid)
3332 : : {
3333 : 14 : Oid elemtype = get_element_type(typid);
3334 : :
3335 [ + + + - ]: 14 : return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
3336 : : }
3337 : :
3338 : :
3339 : : /*
3340 : : * Check whether reltypeId is the row type of a typed table of type
3341 : : * reloftypeId, or is a domain over such a row type. (This is conceptually
3342 : : * similar to the subtype relationship checked by typeInheritsFrom().)
3343 : : */
3344 : : static bool
4852 peter_e@gmx.net 3345 : 335937 : typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
3346 : : {
2362 tgl@sss.pgh.pa.us 3347 : 335937 : Oid relid = typeOrDomainTypeRelid(reltypeId);
4753 bruce@momjian.us 3348 : 335937 : bool result = false;
3349 : :
4852 peter_e@gmx.net 3350 [ + + ]: 335937 : if (relid)
3351 : : {
3352 : : HeapTuple tp;
3353 : : Form_pg_class reltup;
3354 : :
3355 : 6096 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
3356 [ - + ]: 6096 : if (!HeapTupleIsValid(tp))
4852 peter_e@gmx.net 3357 [ # # ]:UBC 0 : elog(ERROR, "cache lookup failed for relation %u", relid);
3358 : :
4852 peter_e@gmx.net 3359 :CBC 6096 : reltup = (Form_pg_class) GETSTRUCT(tp);
3360 [ + + ]: 6096 : if (reltup->reloftype == reloftypeId)
3361 : 6 : result = true;
3362 : :
3363 : 6096 : ReleaseSysCache(tp);
3364 : : }
3365 : :
3366 : 335937 : return result;
3367 : : }
|