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-2025, 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 *
8166 tgl@sss.pgh.pa.us 78 :CBC 374662 : 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 : :
7752 87 [ + + ]: 374662 : if (!can_coerce_type(1, &exprtype, &targettype, ccontext))
88 : 217 : 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 : : */
4996 100 : 374445 : origexpr = expr;
101 [ + - + + ]: 374466 : while (expr && IsA(expr, CollateExpr))
102 : 21 : expr = (Node *) ((CollateExpr *) expr)->arg;
103 : :
7752 104 : 374445 : 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 : 372255 : result = coerce_type_typmod(result,
114 : : targettype, targettypmod,
115 : : ccontext, cformat, location,
116 [ + + + + ]: 372255 : (result != expr && !IsA(result, Const)));
117 : :
1608 118 [ + + + + ]: 372255 : if (expr != origexpr && type_is_collatable(targettype))
119 : : {
120 : : /* Reinstall top CollateExpr */
4996 121 : 18 : CollateExpr *coll = (CollateExpr *) origexpr;
122 : 18 : CollateExpr *newcoll = makeNode(CollateExpr);
123 : :
124 : 18 : newcoll->arg = (Expr *) result;
125 : 18 : newcoll->collOid = coll->collOid;
126 : 18 : newcoll->location = coll->location;
127 : 18 : result = (Node *) newcoll;
128 : : }
129 : :
7752 130 : 372255 : 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 *
8166 157 : 754988 : 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 : :
9298 165 [ + + - + ]: 754988 : if (targetTypeId == inputTypeId ||
166 : : node == NULL)
167 : : {
168 : : /* no conversion needed */
8166 169 : 154167 : return node;
170 : : }
7934 171 [ + + + + ]: 600821 : if (targetTypeId == ANYOID ||
6905 172 [ + + ]: 562596 : targetTypeId == ANYELEMENTOID ||
1997 173 [ + - ]: 555418 : targetTypeId == ANYNONARRAYOID ||
174 [ - + ]: 555418 : 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 : : */
7934 189 : 45403 : return node;
190 : : }
5204 191 [ + + + + ]: 555418 : if (targetTypeId == ANYARRAYOID ||
5056 heikki.linnakangas@i 192 [ + + ]: 539533 : targetTypeId == ANYENUMOID ||
1997 tgl@sss.pgh.pa.us 193 [ + + ]: 535744 : targetTypeId == ANYRANGEOID ||
1721 akorotkov@postgresql 194 [ + - ]: 533229 : targetTypeId == ANYMULTIRANGEOID ||
1997 tgl@sss.pgh.pa.us 195 [ + - ]: 533229 : targetTypeId == ANYCOMPATIBLEARRAYOID ||
1721 akorotkov@postgresql 196 [ - + ]: 533229 : 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 : : */
5204 tgl@sss.pgh.pa.us 214 [ + + ]: 22189 : if (inputTypeId != UNKNOWNOID)
215 : : {
216 : 21621 : Oid baseTypeId = getBaseType(inputTypeId);
217 : :
218 [ + + ]: 21621 : 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 : 21594 : return node;
230 : : }
231 : : }
8166 232 [ + + + + ]: 533797 : 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 : : */
9529 251 : 374165 : Const *con = (Const *) node;
9510 252 : 374165 : 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 : : */
6205 267 : 374165 : baseTypeMod = targetTypeMod;
7094 268 : 374165 : 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 : : */
6205 279 [ + + ]: 374165 : if (baseTypeId == INTERVALOID)
280 : 2569 : inputTypeMod = baseTypeMod;
281 : : else
282 : 371596 : inputTypeMod = -1;
283 : :
3780 noah@leadboat.com 284 : 374165 : baseType = typeidType(baseTypeId);
285 : :
7094 tgl@sss.pgh.pa.us 286 : 374165 : newcon->consttype = baseTypeId;
6205 287 : 374165 : newcon->consttypmod = inputTypeMod;
3780 noah@leadboat.com 288 : 374165 : newcon->constcollid = typeTypeCollation(baseType);
289 : 374165 : newcon->constlen = typeLen(baseType);
290 : 374165 : newcon->constbyval = typeByVal(baseType);
9510 tgl@sss.pgh.pa.us 291 : 374165 : 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 : : */
4911 298 : 374165 : 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 : : */
6214 304 : 374165 : 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 : : */
9278 bruce@momjian.us 310 [ + + ]: 374165 : if (!con->constisnull)
3780 noah@leadboat.com 311 : 336386 : newcon->constvalue = stringTypeDatum(baseType,
312 : : DatumGetCString(con->constvalue),
313 : : inputTypeMod);
314 : : else
315 : 37779 : 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 : : */
3516 tgl@sss.pgh.pa.us 324 [ + + + + ]: 371853 : if (!con->constisnull && newcon->constlen == -1)
325 : 159880 : newcon->constvalue =
326 : 159880 : 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 : :
6214 356 : 371853 : cancel_parser_errposition_callback(&pcbstate);
357 : :
9510 358 : 371853 : result = (Node *) newcon;
359 : :
360 : : /* If target is a domain, apply constraints. */
7094 361 [ + + ]: 371853 : if (baseTypeId != targetTypeId)
362 : 16942 : result = coerce_to_domain(result,
363 : : baseTypeId, baseTypeMod,
364 : : targetTypeId,
365 : : ccontext, cformat, location,
366 : : false);
367 : :
3780 noah@leadboat.com 368 : 371853 : ReleaseSysCache(baseType);
369 : :
8166 tgl@sss.pgh.pa.us 370 : 371853 : return result;
371 : : }
5789 372 [ + + + + ]: 159632 : if (IsA(node, Param) &&
373 [ + + ]: 8514 : 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 : : */
2921 peter_e@gmx.net 380 : 4665 : result = pstate->p_coerce_param_hook(pstate,
381 : : (Param *) node,
382 : : targetTypeId,
383 : : targetTypeMod,
384 : : location);
5789 tgl@sss.pgh.pa.us 385 [ + + ]: 4665 : if (result)
386 : 4623 : return result;
387 : : }
5293 388 [ + + ]: 155009 : 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 : : */
5285 397 : 3812 : CollateExpr *coll = (CollateExpr *) node;
398 : :
1608 399 : 3812 : result = coerce_type(pstate, (Node *) coll->arg,
400 : : inputTypeId, targetTypeId, targetTypeMod,
401 : : ccontext, cformat, location);
402 [ + - ]: 3812 : if (type_is_collatable(targetTypeId))
403 : : {
404 : 3812 : CollateExpr *newcoll = makeNode(CollateExpr);
405 : :
406 : 3812 : newcoll->arg = (Expr *) result;
407 : 3812 : newcoll->collOid = coll->collOid;
408 : 3812 : newcoll->location = coll->location;
409 : 3812 : result = (Node *) newcoll;
410 : : }
411 : 3812 : return result;
412 : : }
6668 413 : 151197 : pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
414 : : &funcId);
415 [ + + ]: 151197 : if (pathtype != COERCION_PATH_NONE)
416 : : {
417 : : Oid baseTypeId;
418 : : int32 baseTypeMod;
419 : :
220 420 : 149550 : baseTypeMod = targetTypeMod;
421 : 149550 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
422 : :
6668 423 [ + + ]: 149550 : if (pathtype != COERCION_PATH_RELABELTYPE)
424 : : {
425 : : /*
426 : : * Generate an expression tree representing run-time application
427 : : * of the conversion function. If we are dealing with a domain
428 : : * target type, the conversion function will yield the base type,
429 : : * and we need to extract the correct typmod to use from the
430 : : * domain's typtypmod.
431 : : */
432 : 46923 : 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 : : */
8406 440 [ + + ]: 46923 : if (targetTypeId != baseTypeId)
7094 441 : 1292 : 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 : : */
220 457 : 102627 : result = coerce_to_domain(node, baseTypeId, baseTypeMod,
458 : : targetTypeId,
459 : : ccontext, cformat, location,
460 : : false);
8251 461 [ + + ]: 102627 : if (result == node)
462 : : {
463 : : /*
464 : : * XXX could we label result with exprTypmod(node) instead of
465 : : * default -1 typmod, to save a possible length-coercion
466 : : * later? Would work if both types have same interpretation of
467 : : * typmod, which is likely but not certain.
468 : : */
6218 469 : 79246 : RelabelType *r = makeRelabelType((Expr *) result,
470 : : targetTypeId, -1,
471 : : InvalidOid,
472 : : cformat);
473 : :
474 : 79246 : r->location = location;
475 : 79246 : result = (Node *) r;
476 : : }
477 : : }
8166 478 : 149550 : return result;
479 : : }
7789 480 [ + + + - ]: 2547 : if (inputTypeId == RECORDOID &&
481 : 900 : ISCOMPLEX(targetTypeId))
482 : : {
483 : : /* Coerce a RECORD to a specific complex type */
484 : 900 : return coerce_record_to_complex(pstate, node, targetTypeId,
485 : : ccontext, cformat, location);
486 : : }
7429 487 [ + + + - ]: 1453 : if (targetTypeId == RECORDOID &&
488 : 706 : ISCOMPLEX(inputTypeId))
489 : : {
490 : : /* Coerce a specific complex type to RECORD */
491 : : /* NB: we do NOT want a RelabelType here */
492 : 706 : return node;
493 : : }
494 : : #ifdef NOT_USED
495 : : if (inputTypeId == RECORDARRAYOID &&
496 : : is_complex_array(targetTypeId))
497 : : {
498 : : /* Coerce record[] to a specific complex array type */
499 : : /* not implemented yet ... */
500 : : }
501 : : #endif
6172 502 [ + + + - ]: 49 : if (targetTypeId == RECORDARRAYOID &&
503 : 8 : is_complex_array(inputTypeId))
504 : : {
505 : : /* Coerce a specific complex array type to record[] */
506 : : /* NB: we do NOT want a RelabelType here */
507 : 8 : return node;
508 : : }
5362 peter_e@gmx.net 509 [ + + ]: 33 : if (typeInheritsFrom(inputTypeId, targetTypeId)
510 [ + - ]: 3 : || typeIsOfTypedTable(inputTypeId, targetTypeId))
511 : : {
512 : : /*
513 : : * Input class type is a subclass of target, so generate an
514 : : * appropriate runtime conversion (removing unneeded columns and
515 : : * possibly rearranging the ones that are wanted).
516 : : *
517 : : * We will also get here when the input is a domain over a subclass of
518 : : * the target type. To keep life simple for the executor, we define
519 : : * ConvertRowtypeExpr as only working between regular composite types;
520 : : * therefore, in such cases insert a RelabelType to smash the input
521 : : * expression down to its base type.
522 : : */
2872 tgl@sss.pgh.pa.us 523 : 33 : Oid baseTypeId = getBaseType(inputTypeId);
7574 524 : 33 : ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
525 : :
2872 526 [ - + ]: 33 : if (baseTypeId != inputTypeId)
527 : : {
2872 tgl@sss.pgh.pa.us 528 :UBC 0 : RelabelType *rt = makeRelabelType((Expr *) node,
529 : : baseTypeId, -1,
530 : : InvalidOid,
531 : : COERCE_IMPLICIT_CAST);
532 : :
533 : 0 : rt->location = location;
534 : 0 : node = (Node *) rt;
535 : : }
7574 tgl@sss.pgh.pa.us 536 :CBC 33 : r->arg = (Expr *) node;
537 : 33 : r->resulttype = targetTypeId;
538 : 33 : r->convertformat = cformat;
6218 539 : 33 : r->location = location;
7574 540 : 33 : return (Node *) r;
541 : : }
542 : : /* If we get here, caller blew it */
8085 tgl@sss.pgh.pa.us 543 [ # # ]:UBC 0 : elog(ERROR, "failed to find conversion function from %s to %s",
544 : : format_type_be(inputTypeId), format_type_be(targetTypeId));
545 : : return NULL; /* keep compiler quiet */
546 : : }
547 : :
548 : :
549 : : /*
550 : : * can_coerce_type()
551 : : * Can input_typeids be coerced to target_typeids?
552 : : *
553 : : * We must be told the context (CAST construct, assignment, implicit coercion)
554 : : * as this determines the set of available casts.
555 : : */
556 : : bool
2510 peter_e@gmx.net 557 :CBC 1036277 : can_coerce_type(int nargs, const Oid *input_typeids, const Oid *target_typeids,
558 : : CoercionContext ccontext)
559 : : {
8187 tgl@sss.pgh.pa.us 560 : 1036277 : bool have_generics = false;
561 : : int i;
562 : :
563 : : /* run through argument list... */
9982 lockhart@fourpalms.o 564 [ + + ]: 1848461 : for (i = 0; i < nargs; i++)
565 : : {
9278 bruce@momjian.us 566 : 1206382 : Oid inputTypeId = input_typeids[i];
8389 tgl@sss.pgh.pa.us 567 : 1206382 : Oid targetTypeId = target_typeids[i];
568 : : CoercionPathType pathtype;
569 : : Oid funcId;
570 : :
571 : : /* no problem if same type */
9305 572 [ + + ]: 1206382 : if (inputTypeId == targetTypeId)
573 : 812184 : continue;
574 : :
575 : : /* accept if target is ANY */
8416 576 [ + + ]: 983871 : if (targetTypeId == ANYOID)
577 : 35524 : continue;
578 : :
579 : : /* accept if target is polymorphic, for now */
6732 580 [ + + + + : 948347 : if (IsPolymorphicType(targetTypeId))
+ + + + +
+ + + + +
+ + + + +
+ + + ]
581 : : {
2999 582 : 97223 : have_generics = true; /* do more checking later */
8187 583 : 97223 : continue;
584 : : }
585 : :
586 : : /*
587 : : * If input is an untyped string constant, assume we can convert it to
588 : : * anything.
589 : : */
7934 590 [ + + ]: 851124 : if (inputTypeId == UNKNOWNOID)
591 : 326561 : continue;
592 : :
593 : : /*
594 : : * If pg_cast shows that we can coerce, accept. This test now covers
595 : : * both binary-compatible and coercion-function cases.
596 : : */
6668 597 : 524563 : pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
598 : : &funcId);
599 [ + + ]: 524563 : if (pathtype != COERCION_PATH_NONE)
8416 600 : 128887 : continue;
601 : :
602 : : /*
603 : : * If input is RECORD and target is a composite type, assume we can
604 : : * coerce (may need tighter checking here)
605 : : */
7789 606 [ + + + + ]: 396645 : if (inputTypeId == RECORDOID &&
607 : 969 : ISCOMPLEX(targetTypeId))
608 : 900 : continue;
609 : :
610 : : /*
611 : : * If input is a composite type and target is RECORD, accept
612 : : */
7429 613 [ + + + + ]: 401331 : if (targetTypeId == RECORDOID &&
614 : 6555 : ISCOMPLEX(inputTypeId))
615 : 545 : continue;
616 : :
617 : : #ifdef NOT_USED /* not implemented yet */
618 : :
619 : : /*
620 : : * If input is record[] and target is a composite array type, assume
621 : : * we can coerce (may need tighter checking here)
622 : : */
623 : : if (inputTypeId == RECORDARRAYOID &&
624 : : is_complex_array(targetTypeId))
625 : : continue;
626 : : #endif
627 : :
628 : : /*
629 : : * If input is a composite array type and target is record[], accept
630 : : */
6172 631 [ + + - + ]: 394237 : if (targetTypeId == RECORDARRAYOID &&
632 : 6 : is_complex_array(inputTypeId))
6172 tgl@sss.pgh.pa.us 633 :UBC 0 : continue;
634 : :
635 : : /*
636 : : * If input is a class type that inherits from target, accept
637 : : */
5362 peter_e@gmx.net 638 [ + + ]:CBC 394231 : if (typeInheritsFrom(inputTypeId, targetTypeId)
639 [ + + ]: 394201 : || typeIsOfTypedTable(inputTypeId, targetTypeId))
9305 tgl@sss.pgh.pa.us 640 : 33 : continue;
641 : :
642 : : /*
643 : : * Else, cannot coerce at this argument position
644 : : */
8406 645 : 394198 : return false;
646 : : }
647 : :
648 : : /* If we found any generic argument types, cross-check them */
8187 649 [ + + ]: 642079 : if (have_generics)
650 : : {
651 [ + + ]: 65182 : if (!check_generic_type_consistency(input_typeids, target_typeids,
652 : : nargs))
653 : 38459 : return false;
654 : : }
655 : :
9982 lockhart@fourpalms.o 656 : 603620 : return true;
657 : : }
658 : :
659 : :
660 : : /*
661 : : * Create an expression tree to represent coercion to a domain type.
662 : : *
663 : : * 'arg': input expression
664 : : * 'baseTypeId': base type of domain
665 : : * 'baseTypeMod': base type typmod of domain
666 : : * 'typeId': target type to coerce to
667 : : * 'ccontext': context indicator to control coercions
668 : : * 'cformat': coercion display format
669 : : * 'location': coercion request location
670 : : * 'hideInputCoercion': if true, hide the input coercion under this one.
671 : : *
672 : : * If the target type isn't a domain, the given 'arg' is returned as-is.
673 : : */
674 : : Node *
7094 tgl@sss.pgh.pa.us 675 : 121187 : coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
676 : : CoercionContext ccontext, CoercionForm cformat, int location,
677 : : bool hideInputCoercion)
678 : : {
679 : : CoerceToDomain *result;
680 : :
681 : : /* We now require the caller to supply correct baseTypeId/baseTypeMod */
220 682 [ - + ]: 121187 : Assert(OidIsValid(baseTypeId));
683 : :
684 : : /* If it isn't a domain, return the node as it was passed in */
8251 685 [ + + ]: 121187 : if (baseTypeId == typeId)
686 : 79246 : return arg;
687 : :
688 : : /* Suppress display of nested coercion steps */
7752 689 [ + + ]: 41941 : if (hideInputCoercion)
690 : 1292 : hide_coercion_node(arg);
691 : :
692 : : /*
693 : : * If the domain applies a typmod to its base type, build the appropriate
694 : : * coercion step. Mark it implicit for display purposes, because we don't
695 : : * want it shown separately by ruleutils.c; but the isExplicit flag passed
696 : : * to the conversion function depends on the manner in which the domain
697 : : * coercion is invoked, so that the semantics of implicit and explicit
698 : : * coercion differ. (Is that really the behavior we want?)
699 : : *
700 : : * NOTE: because we apply this as part of the fixed expression structure,
701 : : * ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
702 : : * would be safe to do anyway, without lots of knowledge about what the
703 : : * base type thinks the typmod means.
704 : : */
2898 705 : 41941 : arg = coerce_type_typmod(arg, baseTypeId, baseTypeMod,
706 : : ccontext, COERCE_IMPLICIT_CAST, location,
707 : : false);
708 : :
709 : : /*
710 : : * Now build the domain coercion node. This represents run-time checking
711 : : * of any constraints currently attached to the domain. This also ensures
712 : : * that the expression is properly labeled as to result type.
713 : : */
8251 714 : 41941 : result = makeNode(CoerceToDomain);
715 : 41941 : result->arg = (Expr *) arg;
716 : 41941 : result->resulttype = typeId;
717 : 41941 : result->resulttypmod = -1; /* currently, always -1 for domains */
718 : : /* resultcollid will be set by parse_collate.c */
719 : 41941 : result->coercionformat = cformat;
6218 720 : 41941 : result->location = location;
721 : :
8251 722 : 41941 : return (Node *) result;
723 : : }
724 : :
725 : :
726 : : /*
727 : : * coerce_type_typmod()
728 : : * Force a value to a particular typmod, if meaningful and possible.
729 : : *
730 : : * This is applied to values that are going to be stored in a relation
731 : : * (where we have an atttypmod for the column) as well as values being
732 : : * explicitly CASTed (where the typmod comes from the target type spec).
733 : : *
734 : : * The caller must have already ensured that the value is of the correct
735 : : * type, typically by applying coerce_type.
736 : : *
737 : : * ccontext may affect semantics, depending on whether the length coercion
738 : : * function pays attention to the isExplicit flag it's passed.
739 : : *
740 : : * cformat determines the display properties of the generated node (if any).
741 : : *
742 : : * If hideInputCoercion is true *and* we generate a node, the input node is
743 : : * forced to IMPLICIT display form, so that only the typmod coercion node will
744 : : * be visible when displaying the expression.
745 : : *
746 : : * NOTE: this does not need to work on domain types, because any typmod
747 : : * coercion for a domain is considered to be part of the type coercion
748 : : * needed to produce the domain value in the first place. So, no getBaseType.
749 : : */
750 : : static Node *
8389 751 : 414196 : coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
752 : : CoercionContext ccontext, CoercionForm cformat,
753 : : int location,
754 : : bool hideInputCoercion)
755 : : {
756 : : CoercionPathType pathtype;
757 : : Oid funcId;
758 : :
759 : : /* Skip coercion if already done */
1492 760 [ + + ]: 414196 : if (targetTypMod == exprTypmod(node))
9364 761 : 404707 : return node;
762 : :
763 : : /* Suppress display of nested coercion steps */
1492 764 [ + + ]: 9489 : if (hideInputCoercion)
765 : 484 : hide_coercion_node(node);
766 : :
767 : : /*
768 : : * A negative typmod means that no actual coercion is needed, but we still
769 : : * want a RelabelType to ensure that the expression exposes the intended
770 : : * typmod.
771 : : */
1360 772 [ + + ]: 9489 : if (targetTypMod < 0)
773 : 15 : pathtype = COERCION_PATH_NONE;
774 : : else
775 : 9474 : pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
776 : :
6668 777 [ + + ]: 9489 : if (pathtype != COERCION_PATH_NONE)
778 : : {
779 : 9468 : node = build_coercion_expression(node, pathtype, funcId,
780 : : targetTypeId, targetTypMod,
781 : : ccontext, cformat, location);
782 : : }
783 : : else
784 : : {
785 : : /*
786 : : * We don't need to perform any actual coercion step, but we should
787 : : * apply a RelabelType to ensure that the expression exposes the
788 : : * intended typmod.
789 : : */
1492 790 : 21 : node = applyRelabelType(node, targetTypeId, targetTypMod,
791 : : exprCollation(node),
792 : : cformat, location, false);
793 : : }
794 : :
7752 795 : 9489 : return node;
796 : : }
797 : :
798 : : /*
799 : : * Mark a coercion node as IMPLICIT so it will never be displayed by
800 : : * ruleutils.c. We use this when we generate a nest of coercion nodes
801 : : * to implement what is logically one conversion; the inner nodes are
802 : : * forced to IMPLICIT_CAST format. This does not change their semantics,
803 : : * only display behavior.
804 : : *
805 : : * It is caller error to call this on something that doesn't have a
806 : : * CoercionForm field.
807 : : */
808 : : static void
809 : 1776 : hide_coercion_node(Node *node)
810 : : {
811 [ + + ]: 1776 : if (IsA(node, FuncExpr))
812 : 826 : ((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
813 [ + + ]: 950 : else if (IsA(node, RelabelType))
814 : 135 : ((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
6668 815 [ + + ]: 815 : else if (IsA(node, CoerceViaIO))
816 : 809 : ((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
6738 817 [ + - ]: 6 : else if (IsA(node, ArrayCoerceExpr))
818 : 6 : ((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
7574 tgl@sss.pgh.pa.us 819 [ # # ]:UBC 0 : else if (IsA(node, ConvertRowtypeExpr))
820 : 0 : ((ConvertRowtypeExpr *) node)->convertformat = COERCE_IMPLICIT_CAST;
7752 821 [ # # ]: 0 : else if (IsA(node, RowExpr))
822 : 0 : ((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
823 [ # # ]: 0 : else if (IsA(node, CoerceToDomain))
824 : 0 : ((CoerceToDomain *) node)->coercionformat = COERCE_IMPLICIT_CAST;
825 : : else
826 [ # # ]: 0 : elog(ERROR, "unsupported node type: %d", (int) nodeTag(node));
7752 tgl@sss.pgh.pa.us 827 :CBC 1776 : }
828 : :
829 : : /*
830 : : * build_coercion_expression()
831 : : * Construct an expression tree for applying a pg_cast entry.
832 : : *
833 : : * This is used for both type-coercion and length-coercion operations,
834 : : * since there is no difference in terms of the calling convention.
835 : : */
836 : : static Node *
6738 837 : 56391 : build_coercion_expression(Node *node,
838 : : CoercionPathType pathtype,
839 : : Oid funcId,
840 : : Oid targetTypeId, int32 targetTypMod,
841 : : CoercionContext ccontext, CoercionForm cformat,
842 : : int location)
843 : : {
844 : 56391 : int nargs = 0;
845 : :
846 [ + + ]: 56391 : if (OidIsValid(funcId))
847 : : {
848 : : HeapTuple tp;
849 : : Form_pg_proc procstruct;
850 : :
5683 rhaas@postgresql.org 851 : 42062 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
6738 tgl@sss.pgh.pa.us 852 [ - + ]: 42062 : if (!HeapTupleIsValid(tp))
6738 tgl@sss.pgh.pa.us 853 [ # # ]:UBC 0 : elog(ERROR, "cache lookup failed for function %u", funcId);
6738 tgl@sss.pgh.pa.us 854 :CBC 42062 : procstruct = (Form_pg_proc) GETSTRUCT(tp);
855 : :
856 : : /*
857 : : * These Asserts essentially check that function is a legal coercion
858 : : * function. We can't make the seemingly obvious tests on prorettype
859 : : * and proargtypes[0], even in the COERCION_PATH_FUNC case, because of
860 : : * various binary-compatibility cases.
861 : : */
862 : : /* Assert(targetTypeId == procstruct->prorettype); */
863 [ - + ]: 42062 : Assert(!procstruct->proretset);
2745 peter_e@gmx.net 864 [ - + ]: 42062 : Assert(procstruct->prokind == PROKIND_FUNCTION);
6738 tgl@sss.pgh.pa.us 865 : 42062 : nargs = procstruct->pronargs;
866 [ + - - + ]: 42062 : Assert(nargs >= 1 && nargs <= 3);
867 : : /* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
868 [ + + - + ]: 42062 : Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
869 [ + + - + ]: 42062 : Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
870 : :
871 : 42062 : ReleaseSysCache(tp);
872 : : }
873 : :
6668 874 [ + + ]: 56391 : if (pathtype == COERCION_PATH_FUNC)
875 : : {
876 : : /* We build an ordinary FuncExpr with special arguments */
877 : : FuncExpr *fexpr;
878 : : List *args;
879 : : Const *cons;
880 : :
6738 881 [ - + ]: 42023 : Assert(OidIsValid(funcId));
882 : :
883 : 42023 : args = list_make1(node);
884 : :
885 [ + + ]: 42023 : if (nargs >= 2)
886 : : {
887 : : /* Pass target typmod as an int4 constant */
888 : 10065 : cons = makeConst(INT4OID,
889 : : -1,
890 : : InvalidOid,
891 : : sizeof(int32),
892 : : Int32GetDatum(targetTypMod),
893 : : false,
894 : : true);
895 : :
896 : 10065 : args = lappend(args, cons);
897 : : }
898 : :
899 [ + + ]: 42023 : if (nargs == 3)
900 : : {
901 : : /* Pass it a boolean isExplicit parameter, too */
902 : 6212 : cons = makeConst(BOOLOID,
903 : : -1,
904 : : InvalidOid,
905 : : sizeof(bool),
906 : : BoolGetDatum(ccontext == COERCION_EXPLICIT),
907 : : false,
908 : : true);
909 : :
910 : 6212 : args = lappend(args, cons);
911 : : }
912 : :
5285 913 : 42023 : fexpr = makeFuncExpr(funcId, targetTypeId, args,
914 : : InvalidOid, InvalidOid, cformat);
6218 915 : 42023 : fexpr->location = location;
916 : 42023 : return (Node *) fexpr;
917 : : }
6668 918 [ + + ]: 14368 : else if (pathtype == COERCION_PATH_ARRAYCOERCE)
919 : : {
920 : : /* We need to build an ArrayCoerceExpr */
921 : 2810 : ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
2898 922 : 2810 : CaseTestExpr *ctest = makeNode(CaseTestExpr);
923 : : Oid sourceBaseTypeId;
924 : : int32 sourceBaseTypeMod;
925 : : Oid targetElementType;
926 : : Node *elemexpr;
927 : :
928 : : /*
929 : : * Look through any domain over the source array type. Note we don't
930 : : * expect that the target type is a domain; it must be a plain array.
931 : : * (To get to a domain target type, we'll do coerce_to_domain later.)
932 : : */
933 : 2810 : sourceBaseTypeMod = exprTypmod(node);
934 : 2810 : sourceBaseTypeId = getBaseTypeAndTypmod(exprType(node),
935 : : &sourceBaseTypeMod);
936 : :
937 : : /*
938 : : * Set up a CaseTestExpr representing one element of the source array.
939 : : * This is an abuse of CaseTestExpr, but it's OK as long as there
940 : : * can't be any CaseExpr or ArrayCoerceExpr within the completed
941 : : * elemexpr.
942 : : */
943 : 2810 : ctest->typeId = get_element_type(sourceBaseTypeId);
944 [ - + ]: 2810 : Assert(OidIsValid(ctest->typeId));
945 : 2810 : ctest->typeMod = sourceBaseTypeMod;
946 : 2810 : ctest->collation = InvalidOid; /* Assume coercions don't care */
947 : :
948 : : /* And coerce it to the target element type */
949 : 2810 : targetElementType = get_element_type(targetTypeId);
950 [ - + ]: 2810 : Assert(OidIsValid(targetElementType));
951 : :
952 : 2810 : elemexpr = coerce_to_target_type(NULL,
953 : : (Node *) ctest,
954 : : ctest->typeId,
955 : : targetElementType,
956 : : targetTypMod,
957 : : ccontext,
958 : : cformat,
959 : : location);
960 [ - + ]: 2810 : if (elemexpr == NULL) /* shouldn't happen */
2898 tgl@sss.pgh.pa.us 961 [ # # ]:UBC 0 : elog(ERROR, "failed to coerce array element type as expected");
962 : :
6668 tgl@sss.pgh.pa.us 963 :CBC 2810 : acoerce->arg = (Expr *) node;
2898 964 : 2810 : acoerce->elemexpr = (Expr *) elemexpr;
6668 965 : 2810 : acoerce->resulttype = targetTypeId;
966 : :
967 : : /*
968 : : * Label the output as having a particular element typmod only if we
969 : : * ended up with a per-element expression that is labeled that way.
970 : : */
2898 971 : 2810 : acoerce->resulttypmod = exprTypmod(elemexpr);
972 : : /* resultcollid will be set by parse_collate.c */
6668 973 : 2810 : acoerce->coerceformat = cformat;
6218 974 : 2810 : acoerce->location = location;
975 : :
6668 976 : 2810 : return (Node *) acoerce;
977 : : }
978 [ + - ]: 11558 : else if (pathtype == COERCION_PATH_COERCEVIAIO)
979 : : {
980 : : /* We need to build a CoerceViaIO node */
981 : 11558 : CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
982 : :
983 [ - + ]: 11558 : Assert(!OidIsValid(funcId));
984 : :
985 : 11558 : iocoerce->arg = (Expr *) node;
986 : 11558 : iocoerce->resulttype = targetTypeId;
987 : : /* resultcollid will be set by parse_collate.c */
988 : 11558 : iocoerce->coerceformat = cformat;
6218 989 : 11558 : iocoerce->location = location;
990 : :
6668 991 : 11558 : return (Node *) iocoerce;
992 : : }
993 : : else
994 : : {
6668 tgl@sss.pgh.pa.us 995 [ # # ]:UBC 0 : elog(ERROR, "unsupported pathtype %d in build_coercion_expression",
996 : : (int) pathtype);
997 : : return NULL; /* keep compiler quiet */
998 : : }
999 : : }
1000 : :
1001 : :
1002 : : /*
1003 : : * coerce_record_to_complex
1004 : : * Coerce a RECORD to a specific composite type.
1005 : : *
1006 : : * Currently we only support this for inputs that are RowExprs or whole-row
1007 : : * Vars.
1008 : : */
1009 : : static Node *
7789 tgl@sss.pgh.pa.us 1010 :CBC 900 : coerce_record_to_complex(ParseState *pstate, Node *node,
1011 : : Oid targetTypeId,
1012 : : CoercionContext ccontext,
1013 : : CoercionForm cformat,
1014 : : int location)
1015 : : {
1016 : : RowExpr *rowexpr;
1017 : : Oid baseTypeId;
2872 1018 : 900 : int32 baseTypeMod = -1;
1019 : : TupleDesc tupdesc;
7789 1020 : 900 : List *args = NIL;
1021 : : List *newargs;
1022 : : int i;
1023 : : int ucolno;
1024 : : ListCell *arg;
1025 : :
1026 [ + - + - ]: 900 : if (node && IsA(node, RowExpr))
1027 : : {
1028 : : /*
1029 : : * Since the RowExpr must be of type RECORD, we needn't worry about it
1030 : : * containing any dropped columns.
1031 : : */
1032 : 900 : args = ((RowExpr *) node)->args;
1033 : : }
7789 tgl@sss.pgh.pa.us 1034 [ # # # # ]:UBC 0 : else if (node && IsA(node, Var) &&
1035 [ # # ]: 0 : ((Var *) node)->varattno == InvalidAttrNumber)
1036 : 0 : {
7678 bruce@momjian.us 1037 : 0 : int rtindex = ((Var *) node)->varno;
1038 : 0 : int sublevels_up = ((Var *) node)->varlevelsup;
6214 tgl@sss.pgh.pa.us 1039 : 0 : int vlocation = ((Var *) node)->location;
1040 : : ParseNamespaceItem *nsitem;
1041 : :
2074 1042 : 0 : nsitem = GetNSItemByRangeTablePosn(pstate, rtindex, sublevels_up);
950 1043 : 0 : args = expandNSItemVars(pstate, nsitem, sublevels_up, vlocation, NULL);
1044 : : }
1045 : : else
7789 1046 [ # # ]: 0 : ereport(ERROR,
1047 : : (errcode(ERRCODE_CANNOT_COERCE),
1048 : : errmsg("cannot cast type %s to %s",
1049 : : format_type_be(RECORDOID),
1050 : : format_type_be(targetTypeId)),
1051 : : parser_coercion_errposition(pstate, location, node)));
1052 : :
1053 : : /*
1054 : : * Look up the composite type, accounting for possibility that what we are
1055 : : * given is a domain over composite.
1056 : : */
2872 tgl@sss.pgh.pa.us 1057 :CBC 900 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
1058 : 900 : tupdesc = lookup_rowtype_tupdesc(baseTypeId, baseTypeMod);
1059 : :
1060 : : /* Process the fields */
7789 1061 : 900 : newargs = NIL;
7690 1062 : 900 : ucolno = 1;
1063 : 900 : arg = list_head(args);
1064 [ + + ]: 2950 : for (i = 0; i < tupdesc->natts; i++)
1065 : : {
1066 : : Node *expr;
1067 : : Node *cexpr;
1068 : : Oid exprtype;
2939 andres@anarazel.de 1069 : 2050 : Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1070 : :
1071 : : /* Fill in NULLs for dropped columns in rowtype */
1072 [ + + ]: 2050 : if (attr->attisdropped)
1073 : : {
1074 : : /*
1075 : : * can't use atttypid here, but it doesn't really matter what type
1076 : : * the Const claims to be.
1077 : : */
5279 tgl@sss.pgh.pa.us 1078 : 3 : newargs = lappend(newargs,
1079 : 3 : makeNullConst(INT4OID, -1, InvalidOid));
7690 1080 : 3 : continue;
1081 : : }
1082 : :
1083 [ - + ]: 2047 : if (arg == NULL)
7690 tgl@sss.pgh.pa.us 1084 [ # # ]:UBC 0 : ereport(ERROR,
1085 : : (errcode(ERRCODE_CANNOT_COERCE),
1086 : : errmsg("cannot cast type %s to %s",
1087 : : format_type_be(RECORDOID),
1088 : : format_type_be(targetTypeId)),
1089 : : errdetail("Input has too few columns."),
1090 : : parser_coercion_errposition(pstate, location, node)));
7690 tgl@sss.pgh.pa.us 1091 :CBC 2047 : expr = (Node *) lfirst(arg);
1092 : 2047 : exprtype = exprType(expr);
1093 : :
6218 1094 : 2047 : cexpr = coerce_to_target_type(pstate,
1095 : : expr, exprtype,
1096 : : attr->atttypid,
1097 : : attr->atttypmod,
1098 : : ccontext,
1099 : : COERCE_IMPLICIT_CAST,
1100 : : -1);
1101 [ - + ]: 2047 : if (cexpr == NULL)
7789 tgl@sss.pgh.pa.us 1102 [ # # ]:UBC 0 : ereport(ERROR,
1103 : : (errcode(ERRCODE_CANNOT_COERCE),
1104 : : errmsg("cannot cast type %s to %s",
1105 : : format_type_be(RECORDOID),
1106 : : format_type_be(targetTypeId)),
1107 : : errdetail("Cannot cast type %s to %s in column %d.",
1108 : : format_type_be(exprtype),
1109 : : format_type_be(attr->atttypid),
1110 : : ucolno),
1111 : : parser_coercion_errposition(pstate, location, expr)));
6218 tgl@sss.pgh.pa.us 1112 :CBC 2047 : newargs = lappend(newargs, cexpr);
7690 1113 : 2047 : ucolno++;
2245 1114 : 2047 : arg = lnext(args, arg);
1115 : : }
7690 1116 [ - + ]: 900 : if (arg != NULL)
7690 tgl@sss.pgh.pa.us 1117 [ # # ]:UBC 0 : ereport(ERROR,
1118 : : (errcode(ERRCODE_CANNOT_COERCE),
1119 : : errmsg("cannot cast type %s to %s",
1120 : : format_type_be(RECORDOID),
1121 : : format_type_be(targetTypeId)),
1122 : : errdetail("Input has too many columns."),
1123 : : parser_coercion_errposition(pstate, location, node)));
1124 : :
7022 tgl@sss.pgh.pa.us 1125 [ + - ]:CBC 900 : ReleaseTupleDesc(tupdesc);
1126 : :
7789 1127 : 900 : rowexpr = makeNode(RowExpr);
1128 : 900 : rowexpr->args = newargs;
2872 1129 : 900 : rowexpr->row_typeid = baseTypeId;
7789 1130 : 900 : rowexpr->row_format = cformat;
6179 1131 : 900 : rowexpr->colnames = NIL; /* not needed for named target type */
6218 1132 : 900 : rowexpr->location = location;
1133 : :
1134 : : /* If target is a domain, apply constraints */
2872 1135 [ + + ]: 900 : if (baseTypeId != targetTypeId)
1136 : : {
1137 : 77 : rowexpr->row_format = COERCE_IMPLICIT_CAST;
1138 : 77 : return coerce_to_domain((Node *) rowexpr,
1139 : : baseTypeId, baseTypeMod,
1140 : : targetTypeId,
1141 : : ccontext, cformat, location,
1142 : : false);
1143 : : }
1144 : :
7789 1145 : 823 : return (Node *) rowexpr;
1146 : : }
1147 : :
1148 : : /*
1149 : : * coerce_to_boolean()
1150 : : * Coerce an argument of a construct that requires boolean input
1151 : : * (AND, OR, NOT, etc). Also check that input is not a set.
1152 : : *
1153 : : * Returns the possibly-transformed node tree.
1154 : : *
1155 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1156 : : * processing is wanted.
1157 : : */
1158 : : Node *
8166 1159 : 395765 : coerce_to_boolean(ParseState *pstate, Node *node,
1160 : : const char *constructName)
1161 : : {
8518 1162 : 395765 : Oid inputTypeId = exprType(node);
1163 : :
1164 [ + + ]: 395765 : if (inputTypeId != BOOLOID)
1165 : : {
1166 : : Node *newnode;
1167 : :
6218 1168 : 36 : newnode = coerce_to_target_type(pstate, node, inputTypeId,
1169 : : BOOLOID, -1,
1170 : : COERCION_ASSIGNMENT,
1171 : : COERCE_IMPLICIT_CAST,
1172 : : -1);
1173 [ + + ]: 36 : if (newnode == NULL)
8085 1174 [ + - ]: 3 : ereport(ERROR,
1175 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1176 : : /* translator: first %s is name of a SQL construct, eg WHERE */
1177 : : errmsg("argument of %s must be type %s, not type %s",
1178 : : constructName, "boolean",
1179 : : format_type_be(inputTypeId)),
1180 : : parser_errposition(pstate, exprLocation(node))));
6218 1181 : 33 : node = newnode;
1182 : : }
1183 : :
8518 1184 [ - + ]: 395762 : if (expression_returns_set(node))
8085 tgl@sss.pgh.pa.us 1185 [ # # ]:UBC 0 : ereport(ERROR,
1186 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1187 : : /* translator: %s is name of a SQL construct, eg WHERE */
1188 : : errmsg("argument of %s must not return a set",
1189 : : constructName),
1190 : : parser_errposition(pstate, exprLocation(node))));
1191 : :
8101 tgl@sss.pgh.pa.us 1192 :CBC 395762 : return node;
1193 : : }
1194 : :
1195 : : /*
1196 : : * coerce_to_specific_type_typmod()
1197 : : * Coerce an argument of a construct that requires a specific data type,
1198 : : * with a specific typmod. Also check that input is not a set.
1199 : : *
1200 : : * Returns the possibly-transformed node tree.
1201 : : *
1202 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1203 : : * processing is wanted.
1204 : : */
1205 : : Node *
3104 alvherre@alvh.no-ip. 1206 : 8234 : coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
1207 : : Oid targetTypeId, int32 targetTypmod,
1208 : : const char *constructName)
1209 : : {
6834 peter_e@gmx.net 1210 : 8234 : Oid inputTypeId = exprType(node);
1211 : :
6831 tgl@sss.pgh.pa.us 1212 [ + + ]: 8234 : if (inputTypeId != targetTypeId)
1213 : : {
1214 : : Node *newnode;
1215 : :
6218 1216 : 5616 : newnode = coerce_to_target_type(pstate, node, inputTypeId,
1217 : : targetTypeId, targetTypmod,
1218 : : COERCION_ASSIGNMENT,
1219 : : COERCE_IMPLICIT_CAST,
1220 : : -1);
1221 [ + + ]: 5610 : if (newnode == NULL)
6834 peter_e@gmx.net 1222 [ + - ]: 3 : ereport(ERROR,
1223 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1224 : : /* translator: first %s is name of a SQL construct, eg LIMIT */
1225 : : errmsg("argument of %s must be type %s, not type %s",
1226 : : constructName,
1227 : : format_type_be(targetTypeId),
1228 : : format_type_be(inputTypeId)),
1229 : : parser_errposition(pstate, exprLocation(node))));
6218 tgl@sss.pgh.pa.us 1230 : 5607 : node = newnode;
1231 : : }
1232 : :
6834 peter_e@gmx.net 1233 [ - + ]: 8225 : if (expression_returns_set(node))
6834 peter_e@gmx.net 1234 [ # # ]:UBC 0 : ereport(ERROR,
1235 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1236 : : /* translator: %s is name of a SQL construct, eg LIMIT */
1237 : : errmsg("argument of %s must not return a set",
1238 : : constructName),
1239 : : parser_errposition(pstate, exprLocation(node))));
1240 : :
6834 peter_e@gmx.net 1241 :CBC 8225 : return node;
1242 : : }
1243 : :
1244 : : /*
1245 : : * coerce_to_specific_type()
1246 : : * Coerce an argument of a construct that requires a specific data type.
1247 : : * Also check that input is not a set.
1248 : : *
1249 : : * Returns the possibly-transformed node tree.
1250 : : *
1251 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1252 : : * processing is wanted.
1253 : : */
1254 : : Node *
3104 alvherre@alvh.no-ip. 1255 : 8206 : coerce_to_specific_type(ParseState *pstate, Node *node,
1256 : : Oid targetTypeId,
1257 : : const char *constructName)
1258 : : {
1259 : 8206 : return coerce_to_specific_type_typmod(pstate, node,
1260 : : targetTypeId, -1,
1261 : : constructName);
1262 : : }
1263 : :
1264 : : /*
1265 : : * coerce_null_to_domain()
1266 : : * Build a NULL constant, then wrap it in CoerceToDomain
1267 : : * if the desired type is a domain type. This allows any
1268 : : * NOT NULL domain constraint to be enforced at runtime.
1269 : : */
1270 : : Node *
220 tgl@sss.pgh.pa.us 1271 : 8970 : coerce_null_to_domain(Oid typid, int32 typmod, Oid collation,
1272 : : int typlen, bool typbyval)
1273 : : {
1274 : : Node *result;
1275 : : Oid baseTypeId;
1276 : 8970 : int32 baseTypeMod = typmod;
1277 : :
1278 : : /*
1279 : : * The constant must appear to have the domain's base type/typmod, else
1280 : : * coerce_to_domain() will apply a length coercion which is useless.
1281 : : */
1282 : 8970 : baseTypeId = getBaseTypeAndTypmod(typid, &baseTypeMod);
1283 : 8970 : result = (Node *) makeConst(baseTypeId,
1284 : : baseTypeMod,
1285 : : collation,
1286 : : typlen,
1287 : : (Datum) 0,
1288 : : true, /* isnull */
1289 : : typbyval);
1290 [ + + ]: 8970 : if (typid != baseTypeId)
1291 : 33 : result = coerce_to_domain(result,
1292 : : baseTypeId, baseTypeMod,
1293 : : typid,
1294 : : COERCION_IMPLICIT,
1295 : : COERCE_IMPLICIT_CAST,
1296 : : -1,
1297 : : false);
1298 : 8970 : return result;
1299 : : }
1300 : :
1301 : : /*
1302 : : * parser_coercion_errposition - report coercion error location, if possible
1303 : : *
1304 : : * We prefer to point at the coercion request (CAST, ::, etc) if possible;
1305 : : * but there may be no such location in the case of an implicit coercion.
1306 : : * In that case point at the input expression.
1307 : : *
1308 : : * XXX possibly this is more generally useful than coercion errors;
1309 : : * if so, should rename and place with parser_errposition.
1310 : : */
1311 : : int
6218 1312 : 11 : parser_coercion_errposition(ParseState *pstate,
1313 : : int coerce_location,
1314 : : Node *input_expr)
1315 : : {
1316 [ + - ]: 11 : if (coerce_location >= 0)
1991 1317 : 11 : return parser_errposition(pstate, coerce_location);
1318 : : else
1991 tgl@sss.pgh.pa.us 1319 :UBC 0 : return parser_errposition(pstate, exprLocation(input_expr));
1320 : : }
1321 : :
1322 : :
1323 : : /*
1324 : : * select_common_type()
1325 : : * Determine the common supertype of a list of input expressions.
1326 : : * This is used for determining the output type of CASE, UNION,
1327 : : * and similar constructs.
1328 : : *
1329 : : * 'exprs' is a *nonempty* list of expressions. Note that earlier items
1330 : : * in the list will be preferred if there is doubt.
1331 : : * 'context' is a phrase to use in the error message if we fail to select
1332 : : * a usable type. Pass NULL to have the routine return InvalidOid
1333 : : * rather than throwing an error on failure.
1334 : : * 'which_expr': if not NULL, receives a pointer to the particular input
1335 : : * expression from which the result type was taken.
1336 : : *
1337 : : * Caution: "failure" just means that there were inputs of different type
1338 : : * categories. It is not guaranteed that all the inputs are coercible to the
1339 : : * selected type; caller must check that (see verify_common_type).
1340 : : */
1341 : : Oid
6218 tgl@sss.pgh.pa.us 1342 :CBC 70365 : select_common_type(ParseState *pstate, List *exprs, const char *context,
1343 : : Node **which_expr)
1344 : : {
1345 : : Node *pexpr;
1346 : : Oid ptype;
1347 : : TYPCATEGORY pcategory;
1348 : : bool pispreferred;
1349 : : ListCell *lc;
1350 : :
1351 [ - + ]: 70365 : Assert(exprs != NIL);
1352 : 70365 : pexpr = (Node *) linitial(exprs);
2245 1353 : 70365 : lc = list_second_cell(exprs);
6218 1354 : 70365 : ptype = exprType(pexpr);
1355 : :
1356 : : /*
1357 : : * If all input types are valid and exactly the same, just pick that type.
1358 : : * This is the only way that we will resolve the result as being a domain
1359 : : * type; otherwise domains are smashed to their base types for comparison.
1360 : : */
6494 1361 [ + + ]: 70365 : if (ptype != UNKNOWNOID)
1362 : : {
2245 1363 [ + - + + : 92337 : for_each_cell(lc, exprs, lc)
+ + ]
1364 : : {
5931 bruce@momjian.us 1365 : 58609 : Node *nexpr = (Node *) lfirst(lc);
1366 : 58609 : Oid ntype = exprType(nexpr);
1367 : :
6494 tgl@sss.pgh.pa.us 1368 [ + + ]: 58609 : if (ntype != ptype)
1369 : 19971 : break;
1370 : : }
6218 1371 [ + + ]: 53699 : if (lc == NULL) /* got to the end of the list? */
1372 : : {
1373 [ + + ]: 33728 : if (which_expr)
1374 : 22253 : *which_expr = pexpr;
6494 1375 : 33728 : return ptype;
1376 : : }
1377 : : }
1378 : :
1379 : : /*
1380 : : * Nope, so set up for the full algorithm. Note that at this point, lc
1381 : : * points to the first list item with type different from pexpr's; we need
1382 : : * not re-examine any items the previous loop advanced over.
1383 : : */
1384 : 36637 : ptype = getBaseType(ptype);
6247 1385 : 36637 : get_type_category_preferred(ptype, &pcategory, &pispreferred);
1386 : :
2245 1387 [ + - + + : 107498 : for_each_cell(lc, exprs, lc)
+ + ]
1388 : : {
6218 1389 : 70869 : Node *nexpr = (Node *) lfirst(lc);
1390 : 70869 : Oid ntype = getBaseType(exprType(nexpr));
1391 : :
1392 : : /* move on to next one if no new information... */
6494 1393 [ + + + + ]: 70869 : if (ntype != UNKNOWNOID && ntype != ptype)
1394 : : {
1395 : : TYPCATEGORY ncategory;
1396 : : bool nispreferred;
1397 : :
6247 1398 : 13532 : get_type_category_preferred(ntype, &ncategory, &nispreferred);
6494 1399 [ + + ]: 13532 : if (ptype == UNKNOWNOID)
1400 : : {
1401 : : /* so far, only unknowns so take anything... */
6218 1402 : 9579 : pexpr = nexpr;
9102 1403 : 9579 : ptype = ntype;
6247 1404 : 9579 : pcategory = ncategory;
1405 : 9579 : pispreferred = nispreferred;
1406 : : }
1407 [ + + ]: 3953 : else if (ncategory != pcategory)
1408 : : {
1409 : : /*
1410 : : * both types in different categories? then not much hope...
1411 : : */
6160 1412 [ + + ]: 8 : if (context == NULL)
1413 : 2 : return InvalidOid;
8085 1414 [ + - ]: 6 : ereport(ERROR,
1415 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1416 : : /*------
1417 : : translator: first %s is name of a SQL construct, eg CASE */
1418 : : errmsg("%s types %s and %s cannot be matched",
1419 : : context,
1420 : : format_type_be(ptype),
1421 : : format_type_be(ntype)),
1422 : : parser_errposition(pstate, exprLocation(nexpr))));
1423 : : }
6247 1424 [ + + + + ]: 5166 : else if (!pispreferred &&
7266 bruce@momjian.us 1425 : 1221 : can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
1426 [ + + ]: 787 : !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
1427 : : {
1428 : : /*
1429 : : * take new type if can coerce to it implicitly but not the
1430 : : * other way; but if we have a preferred type, stay on it.
1431 : : */
6218 tgl@sss.pgh.pa.us 1432 : 691 : pexpr = nexpr;
9102 1433 : 691 : ptype = ntype;
6247 1434 : 691 : pcategory = ncategory;
1435 : 691 : pispreferred = nispreferred;
1436 : : }
1437 : : }
1438 : : }
1439 : :
1440 : : /*
1441 : : * If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
1442 : : * then resolve as type TEXT. This situation comes up with constructs
1443 : : * like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
1444 : : * UNION SELECT 'bar'; It might seem desirable to leave the construct's
1445 : : * output type as UNKNOWN, but that really doesn't work, because we'd
1446 : : * probably end up needing a runtime coercion from UNKNOWN to something
1447 : : * else, and we usually won't have it. We need to coerce the unknown
1448 : : * literals while they are still literals, so a decision has to be made
1449 : : * now.
1450 : : */
9067 1451 [ + + ]: 36629 : if (ptype == UNKNOWNOID)
1452 : 7087 : ptype = TEXTOID;
1453 : :
6218 1454 [ + + ]: 36629 : if (which_expr)
1455 : 7609 : *which_expr = pexpr;
9102 1456 : 36629 : return ptype;
1457 : : }
1458 : :
1459 : : /*
1460 : : * select_common_type_from_oids()
1461 : : * Determine the common supertype of an array of type OIDs.
1462 : : *
1463 : : * This is the same logic as select_common_type(), but working from
1464 : : * an array of type OIDs not a list of expressions. As in that function,
1465 : : * earlier entries in the array have some preference over later ones.
1466 : : * On failure, return InvalidOid if noerror is true, else throw an error.
1467 : : *
1468 : : * Caution: "failure" just means that there were inputs of different type
1469 : : * categories. It is not guaranteed that all the inputs are coercible to the
1470 : : * selected type; caller must check that (see verify_common_type_from_oids).
1471 : : *
1472 : : * Note: neither caller will pass any UNKNOWNOID entries, so the tests
1473 : : * for that in this function are dead code. However, they don't cost much,
1474 : : * and it seems better to keep this logic as close to select_common_type()
1475 : : * as possible.
1476 : : */
1477 : : static Oid
1997 1478 : 3712 : select_common_type_from_oids(int nargs, const Oid *typeids, bool noerror)
1479 : : {
1480 : : Oid ptype;
1481 : : TYPCATEGORY pcategory;
1482 : : bool pispreferred;
1483 : 3712 : int i = 1;
1484 : :
1485 [ - + ]: 3712 : Assert(nargs > 0);
1486 : 3712 : ptype = typeids[0];
1487 : :
1488 : : /* If all input types are valid and exactly the same, pick that type. */
1489 [ + - ]: 3712 : if (ptype != UNKNOWNOID)
1490 : : {
1491 [ + + ]: 5399 : for (; i < nargs; i++)
1492 : : {
1493 [ + + ]: 2236 : if (typeids[i] != ptype)
1494 : 549 : break;
1495 : : }
1496 [ + + ]: 3712 : if (i == nargs)
1497 : 3163 : return ptype;
1498 : : }
1499 : :
1500 : : /*
1501 : : * Nope, so set up for the full algorithm. Note that at this point, we
1502 : : * can skip array entries before "i"; they are all equal to ptype.
1503 : : */
1504 : 549 : ptype = getBaseType(ptype);
1505 : 549 : get_type_category_preferred(ptype, &pcategory, &pispreferred);
1506 : :
1507 [ + + ]: 801 : for (; i < nargs; i++)
1508 : : {
1509 : 576 : Oid ntype = getBaseType(typeids[i]);
1510 : :
1511 : : /* move on to next one if no new information... */
1512 [ + - + + ]: 576 : if (ntype != UNKNOWNOID && ntype != ptype)
1513 : : {
1514 : : TYPCATEGORY ncategory;
1515 : : bool nispreferred;
1516 : :
1517 : 570 : get_type_category_preferred(ntype, &ncategory, &nispreferred);
1518 [ - + ]: 570 : if (ptype == UNKNOWNOID)
1519 : : {
1520 : : /* so far, only unknowns so take anything... */
1997 tgl@sss.pgh.pa.us 1521 :UBC 0 : ptype = ntype;
1522 : 0 : pcategory = ncategory;
1523 : 0 : pispreferred = nispreferred;
1524 : : }
1997 tgl@sss.pgh.pa.us 1525 [ + + ]:CBC 570 : else if (ncategory != pcategory)
1526 : : {
1527 : : /*
1528 : : * both types in different categories? then not much hope...
1529 : : */
1530 [ + - ]: 324 : if (noerror)
1531 : 324 : return InvalidOid;
1997 tgl@sss.pgh.pa.us 1532 [ # # ]:UBC 0 : ereport(ERROR,
1533 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
1534 : : errmsg("argument types %s and %s cannot be matched",
1535 : : format_type_be(ptype),
1536 : : format_type_be(ntype))));
1537 : : }
1997 tgl@sss.pgh.pa.us 1538 [ + + + + ]:CBC 456 : else if (!pispreferred &&
1539 : 210 : can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
1540 [ + - ]: 135 : !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
1541 : : {
1542 : : /*
1543 : : * take new type if can coerce to it implicitly but not the
1544 : : * other way; but if we have a preferred type, stay on it.
1545 : : */
1546 : 135 : ptype = ntype;
1547 : 135 : pcategory = ncategory;
1548 : 135 : pispreferred = nispreferred;
1549 : : }
1550 : : }
1551 : : }
1552 : :
1553 : : /* Like select_common_type(), choose TEXT if all inputs were UNKNOWN */
1554 [ - + ]: 225 : if (ptype == UNKNOWNOID)
1997 tgl@sss.pgh.pa.us 1555 :UBC 0 : ptype = TEXTOID;
1556 : :
1997 tgl@sss.pgh.pa.us 1557 :CBC 225 : return ptype;
1558 : : }
1559 : :
1560 : : /*
1561 : : * coerce_to_common_type()
1562 : : * Coerce an expression to the given type.
1563 : : *
1564 : : * This is used following select_common_type() to coerce the individual
1565 : : * expressions to the desired type. 'context' is a phrase to use in the
1566 : : * error message if we fail to coerce.
1567 : : *
1568 : : * As with coerce_type, pstate may be NULL if no special unknown-Param
1569 : : * processing is wanted.
1570 : : */
1571 : : Node *
8166 1572 : 169645 : coerce_to_common_type(ParseState *pstate, Node *node,
1573 : : Oid targetTypeId, const char *context)
1574 : : {
9102 1575 : 169645 : Oid inputTypeId = exprType(node);
1576 : :
1577 [ + + ]: 169645 : if (inputTypeId == targetTypeId)
1578 : 96130 : return node; /* no work */
8389 1579 [ + - ]: 73515 : if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
7752 1580 : 73515 : node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
1581 : : COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
1582 : : else
8085 tgl@sss.pgh.pa.us 1583 [ # # ]:UBC 0 : ereport(ERROR,
1584 : : (errcode(ERRCODE_CANNOT_COERCE),
1585 : : /* translator: first %s is name of a SQL construct, eg CASE */
1586 : : errmsg("%s could not convert type %s to %s",
1587 : : context,
1588 : : format_type_be(inputTypeId),
1589 : : format_type_be(targetTypeId)),
1590 : : parser_errposition(pstate, exprLocation(node))));
9102 tgl@sss.pgh.pa.us 1591 :CBC 73512 : return node;
1592 : : }
1593 : :
1594 : : /*
1595 : : * verify_common_type()
1596 : : * Verify that all input types can be coerced to a proposed common type.
1597 : : * Return true if so, false if not all coercions are possible.
1598 : : *
1599 : : * Most callers of select_common_type() don't need to do this explicitly
1600 : : * because the checks will happen while trying to convert input expressions
1601 : : * to the right type, e.g. in coerce_to_common_type(). However, if a separate
1602 : : * check step is needed to validate the applicability of the common type, call
1603 : : * this.
1604 : : */
1605 : : bool
1316 1606 : 9109 : verify_common_type(Oid common_type, List *exprs)
1607 : : {
1608 : : ListCell *lc;
1609 : :
1610 [ + - + + : 45690 : foreach(lc, exprs)
+ + ]
1611 : : {
1612 : 36584 : Node *nexpr = (Node *) lfirst(lc);
1613 : 36584 : Oid ntype = exprType(nexpr);
1614 : :
1615 [ + + ]: 36584 : if (!can_coerce_type(1, &ntype, &common_type, COERCION_IMPLICIT))
1616 : 3 : return false;
1617 : : }
1618 : 9106 : return true;
1619 : : }
1620 : :
1621 : : /*
1622 : : * verify_common_type_from_oids()
1623 : : * As above, but work from an array of type OIDs.
1624 : : */
1625 : : static bool
1626 : 3388 : verify_common_type_from_oids(Oid common_type, int nargs, const Oid *typeids)
1627 : : {
1628 [ + + ]: 8709 : for (int i = 0; i < nargs; i++)
1629 : : {
1630 [ + + ]: 5327 : if (!can_coerce_type(1, &typeids[i], &common_type, COERCION_IMPLICIT))
1631 : 6 : return false;
1632 : : }
1633 : 3382 : return true;
1634 : : }
1635 : :
1636 : : /*
1637 : : * select_common_typmod()
1638 : : * Determine the common typmod of a list of input expressions.
1639 : : *
1640 : : * common_type is the selected common type of the expressions, typically
1641 : : * computed using select_common_type().
1642 : : */
1643 : : int32
1775 peter@eisentraut.org 1644 : 36421 : select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
1645 : : {
1646 : : ListCell *lc;
1647 : 36421 : bool first = true;
1648 : 36421 : int32 result = -1;
1649 : :
1650 [ + - + + : 114041 : foreach(lc, exprs)
+ + ]
1651 : : {
1706 tgl@sss.pgh.pa.us 1652 : 77731 : Node *expr = (Node *) lfirst(lc);
1653 : :
1654 : : /* Types must match */
1775 peter@eisentraut.org 1655 [ + + ]: 77731 : if (exprType(expr) != common_type)
1656 : 111 : return -1;
1657 [ + + ]: 77641 : else if (first)
1658 : : {
1659 : 36376 : result = exprTypmod(expr);
1660 : 36376 : first = false;
1661 : : }
1662 : : else
1663 : : {
1664 : : /* As soon as we see a non-matching typmod, fall back to -1 */
1665 [ + + ]: 41265 : if (result != exprTypmod(expr))
1666 : 21 : return -1;
1667 : : }
1668 : : }
1669 : :
1670 : 36310 : return result;
1671 : : }
1672 : :
1673 : : /*
1674 : : * check_generic_type_consistency()
1675 : : * Are the actual arguments potentially compatible with a
1676 : : * polymorphic function?
1677 : : *
1678 : : * The argument consistency rules are:
1679 : : *
1680 : : * 1) All arguments declared ANYELEMENT must have the same datatype.
1681 : : * 2) All arguments declared ANYARRAY must have the same datatype,
1682 : : * which must be a varlena array type.
1683 : : * 3) All arguments declared ANYRANGE must be the same range type.
1684 : : * Similarly, all arguments declared ANYMULTIRANGE must be the same
1685 : : * multirange type; and if both of these appear, the ANYRANGE type
1686 : : * must be the element type of the ANYMULTIRANGE type.
1687 : : * 4) If there are arguments of more than one of these polymorphic types,
1688 : : * the array element type and/or range subtype must be the same as each
1689 : : * other and the same as the ANYELEMENT type.
1690 : : * 5) ANYENUM is treated the same as ANYELEMENT except that if it is used
1691 : : * (alone or in combination with plain ANYELEMENT), we add the extra
1692 : : * condition that the ANYELEMENT type must be an enum.
1693 : : * 6) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
1694 : : * we add the extra condition that the ANYELEMENT type must not be an array.
1695 : : * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
1696 : : * is an extra restriction if not.)
1697 : : * 7) All arguments declared ANYCOMPATIBLE must be implicitly castable
1698 : : * to a common supertype (chosen as per select_common_type's rules).
1699 : : * ANYCOMPATIBLENONARRAY works like ANYCOMPATIBLE but also requires the
1700 : : * common supertype to not be an array. If there are ANYCOMPATIBLEARRAY
1701 : : * or ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE arguments, their element
1702 : : * types or subtypes are included while making the choice of common supertype.
1703 : : * 8) The resolved type of ANYCOMPATIBLEARRAY arguments will be the array
1704 : : * type over the common supertype (which might not be the same array type
1705 : : * as any of the original arrays).
1706 : : * 9) All ANYCOMPATIBLERANGE arguments must be the exact same range type
1707 : : * (after domain flattening), since we have no preference rule that would
1708 : : * let us choose one over another. Furthermore, that range's subtype
1709 : : * must exactly match the common supertype chosen by rule 7.
1710 : : * 10) All ANYCOMPATIBLEMULTIRANGE arguments must be the exact same multirange
1711 : : * type (after domain flattening), since we have no preference rule that
1712 : : * would let us choose one over another. Furthermore, if ANYCOMPATIBLERANGE
1713 : : * also appears, that range type must be the multirange's element type;
1714 : : * otherwise, the multirange's range's subtype must exactly match the
1715 : : * common supertype chosen by rule 7.
1716 : : *
1717 : : * Domains over arrays match ANYARRAY, and are immediately flattened to their
1718 : : * base type. (Thus, for example, we will consider it a match if one ANYARRAY
1719 : : * argument is a domain over int4[] while another one is just int4[].) Also
1720 : : * notice that such a domain does *not* match ANYNONARRAY. The same goes
1721 : : * for ANYCOMPATIBLEARRAY and ANYCOMPATIBLENONARRAY.
1722 : : *
1723 : : * Similarly, domains over ranges match ANYRANGE or ANYCOMPATIBLERANGE,
1724 : : * and are immediately flattened to their base type. Likewise, domains
1725 : : * over multiranges match ANYMULTIRANGE or ANYCOMPATIBLEMULTIRANGE and are
1726 : : * immediately flattened to their base type.
1727 : : *
1728 : : * Note that domains aren't currently considered to match ANYENUM,
1729 : : * even if their base type would match.
1730 : : *
1731 : : * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
1732 : : * argument, assume it is okay.
1733 : : *
1734 : : * We do not ereport here, but just return false if a rule is violated.
1735 : : */
1736 : : bool
2510 peter_e@gmx.net 1737 : 65182 : check_generic_type_consistency(const Oid *actual_arg_types,
1738 : : const Oid *declared_arg_types,
1739 : : int nargs)
1740 : : {
8187 tgl@sss.pgh.pa.us 1741 : 65182 : Oid elem_typeid = InvalidOid;
1742 : 65182 : Oid array_typeid = InvalidOid;
5056 heikki.linnakangas@i 1743 : 65182 : Oid range_typeid = InvalidOid;
1721 akorotkov@postgresql 1744 : 65182 : Oid multirange_typeid = InvalidOid;
1997 tgl@sss.pgh.pa.us 1745 : 65182 : Oid anycompatible_range_typeid = InvalidOid;
1746 : 65182 : Oid anycompatible_range_typelem = InvalidOid;
1721 akorotkov@postgresql 1747 : 65182 : Oid anycompatible_multirange_typeid = InvalidOid;
1748 : 65182 : Oid anycompatible_multirange_typelem = InvalidOid;
1749 : 65182 : Oid range_typelem = InvalidOid;
6667 tgl@sss.pgh.pa.us 1750 : 65182 : bool have_anynonarray = false;
6732 1751 : 65182 : bool have_anyenum = false;
1997 1752 : 65182 : bool have_anycompatible_nonarray = false;
1753 : 65182 : int n_anycompatible_args = 0;
1754 : : Oid anycompatible_actual_types[FUNC_MAX_ARGS];
1755 : :
1756 : : /*
1757 : : * Loop through the arguments to see if we have any that are polymorphic.
1758 : : * If so, require the actual types to be consistent.
1759 : : */
1760 [ - + ]: 65182 : Assert(nargs <= FUNC_MAX_ARGS);
1999 1761 [ + + ]: 151504 : for (int j = 0; j < nargs; j++)
1762 : : {
6667 1763 : 105608 : Oid decl_type = declared_arg_types[j];
8069 bruce@momjian.us 1764 : 105608 : Oid actual_type = actual_arg_types[j];
1765 : :
6667 tgl@sss.pgh.pa.us 1766 [ + + + + ]: 105608 : if (decl_type == ANYELEMENTOID ||
1767 [ + + ]: 94922 : decl_type == ANYNONARRAYOID ||
1768 : : decl_type == ANYENUMOID)
1769 : : {
1770 [ + + ]: 22983 : if (decl_type == ANYNONARRAYOID)
1771 : 7712 : have_anynonarray = true;
1772 [ + + ]: 15271 : else if (decl_type == ANYENUMOID)
6732 1773 : 12297 : have_anyenum = true;
8187 1774 [ + + ]: 22983 : if (actual_type == UNKNOWNOID)
1775 : 1343 : continue;
1776 [ + + + + ]: 21640 : if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
1777 : 4376 : return false;
1778 : 17264 : elem_typeid = actual_type;
1779 : : }
6667 1780 [ + + ]: 82625 : else if (decl_type == ANYARRAYOID)
1781 : : {
8187 1782 [ + + ]: 31515 : if (actual_type == UNKNOWNOID)
1783 : 1544 : continue;
2999 1784 : 29971 : actual_type = getBaseType(actual_type); /* flatten domains */
8187 1785 [ + + + + ]: 29971 : if (OidIsValid(array_typeid) && actual_type != array_typeid)
1786 : 4340 : return false;
1787 : 25631 : array_typeid = actual_type;
1788 : : }
5056 heikki.linnakangas@i 1789 [ + + ]: 51110 : else if (decl_type == ANYRANGEOID)
1790 : : {
1791 [ + + ]: 16993 : if (actual_type == UNKNOWNOID)
1792 : 1118 : continue;
2999 tgl@sss.pgh.pa.us 1793 : 15875 : actual_type = getBaseType(actual_type); /* flatten domains */
5056 heikki.linnakangas@i 1794 [ + + + + ]: 15875 : if (OidIsValid(range_typeid) && actual_type != range_typeid)
1795 : 4778 : return false;
1796 : 11097 : range_typeid = actual_type;
1797 : : }
1721 akorotkov@postgresql 1798 [ + + ]: 34117 : else if (decl_type == ANYMULTIRANGEOID)
1799 : : {
1800 [ + + ]: 19640 : if (actual_type == UNKNOWNOID)
1801 : 1127 : continue;
1802 : 18513 : actual_type = getBaseType(actual_type); /* flatten domains */
1803 [ + + + + ]: 18513 : if (OidIsValid(multirange_typeid) && actual_type != multirange_typeid)
1804 : 4775 : return false;
1805 : 13738 : multirange_typeid = actual_type;
1806 : : }
1997 tgl@sss.pgh.pa.us 1807 [ + + + + ]: 14477 : else if (decl_type == ANYCOMPATIBLEOID ||
1808 : : decl_type == ANYCOMPATIBLENONARRAYOID)
1809 : : {
1810 [ + + ]: 2078 : if (decl_type == ANYCOMPATIBLENONARRAYOID)
1811 : 18 : have_anycompatible_nonarray = true;
1812 [ + + ]: 2078 : if (actual_type == UNKNOWNOID)
1813 : 804 : continue;
1814 : : /* collect the actual types of non-unknown COMPATIBLE args */
1815 : 1274 : anycompatible_actual_types[n_anycompatible_args++] = actual_type;
1816 : : }
1817 [ + + ]: 12399 : else if (decl_type == ANYCOMPATIBLEARRAYOID)
1818 : : {
1819 : : Oid elem_type;
1820 : :
1821 [ + + ]: 3056 : if (actual_type == UNKNOWNOID)
1822 : 533 : continue;
1823 : 2523 : actual_type = getBaseType(actual_type); /* flatten domains */
1824 : 2523 : elem_type = get_element_type(actual_type);
1825 [ + + ]: 2523 : if (!OidIsValid(elem_type))
1826 : 1005 : return false; /* not an array */
1827 : : /* collect the element type for common-supertype choice */
1828 : 1518 : anycompatible_actual_types[n_anycompatible_args++] = elem_type;
1829 : : }
1830 [ + + ]: 9343 : else if (decl_type == ANYCOMPATIBLERANGEOID)
1831 : : {
1832 [ + + ]: 93 : if (actual_type == UNKNOWNOID)
1833 : 6 : continue;
1834 : 87 : actual_type = getBaseType(actual_type); /* flatten domains */
1835 [ + + ]: 87 : if (OidIsValid(anycompatible_range_typeid))
1836 : : {
1837 : : /* All ANYCOMPATIBLERANGE arguments must be the same type */
1838 [ + + ]: 6 : if (anycompatible_range_typeid != actual_type)
1839 : 3 : return false;
1840 : : }
1841 : : else
1842 : : {
1843 : 81 : anycompatible_range_typeid = actual_type;
1844 : 81 : anycompatible_range_typelem = get_range_subtype(actual_type);
1845 [ + + ]: 81 : if (!OidIsValid(anycompatible_range_typelem))
1846 : 3 : return false; /* not a range type */
1847 : : /* collect the subtype for common-supertype choice */
1848 : 78 : anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
1849 : : }
1850 : : }
1721 akorotkov@postgresql 1851 [ + + ]: 9250 : else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
1852 : : {
1853 [ + + ]: 69 : if (actual_type == UNKNOWNOID)
1854 : 9 : continue;
1855 : 60 : actual_type = getBaseType(actual_type); /* flatten domains */
1856 [ + + ]: 60 : if (OidIsValid(anycompatible_multirange_typeid))
1857 : : {
1858 : : /* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
1859 [ + + ]: 6 : if (anycompatible_multirange_typeid != actual_type)
1860 : 3 : return false;
1861 : : }
1862 : : else
1863 : : {
1864 : 54 : anycompatible_multirange_typeid = actual_type;
1865 : 54 : anycompatible_multirange_typelem = get_multirange_range(actual_type);
1866 [ + + ]: 54 : if (!OidIsValid(anycompatible_multirange_typelem))
1867 : 3 : return false; /* not a multirange type */
1868 : : /* we'll consider the subtype below */
1869 : : }
1870 : : }
1871 : : }
1872 : :
1873 : : /* Get the element type based on the array type, if we have one */
8187 tgl@sss.pgh.pa.us 1874 [ + + ]: 45896 : if (OidIsValid(array_typeid))
1875 : : {
8019 1876 [ + - ]: 20136 : if (array_typeid == ANYARRAYOID)
1877 : : {
1878 : : /*
1879 : : * Special case for matching ANYARRAY input to an ANYARRAY
1880 : : * argument: allow it for now. enforce_generic_type_consistency()
1881 : : * might complain later, depending on the presence of other
1882 : : * polymorphic arguments or results, but it will deliver a less
1883 : : * surprising error message than "function does not exist".
1884 : : *
1885 : : * (If you think to change this, note that can_coerce_type will
1886 : : * consider such a situation as a match, so that we might not even
1887 : : * get here.)
1888 : : */
1889 : : }
1890 : : else
1891 : : {
1892 : : Oid array_typelem;
1893 : :
1999 1894 : 20136 : array_typelem = get_element_type(array_typeid);
1895 [ + + ]: 20136 : if (!OidIsValid(array_typelem))
1896 : 7620 : return false; /* should be an array, but isn't */
1897 : :
1898 [ + + ]: 12516 : if (!OidIsValid(elem_typeid))
1899 : : {
1900 : : /*
1901 : : * if we don't have an element type yet, use the one we just
1902 : : * got
1903 : : */
1904 : 12450 : elem_typeid = array_typelem;
1905 : : }
1906 [ + + ]: 66 : else if (array_typelem != elem_typeid)
1907 : : {
1908 : : /* otherwise, they better match */
1909 : 25 : return false;
1910 : : }
1911 : : }
1912 : : }
1913 : :
1914 : : /* Deduce range type from multirange type, or check that they agree */
1721 akorotkov@postgresql 1915 [ + + ]: 38251 : if (OidIsValid(multirange_typeid))
1916 : : {
1917 : : Oid multirange_typelem;
1918 : :
1919 : 7658 : multirange_typelem = get_multirange_range(multirange_typeid);
1920 [ + + ]: 7658 : if (!OidIsValid(multirange_typelem))
1921 : 6630 : return false; /* should be a multirange, but isn't */
1922 : :
1923 [ + + ]: 1028 : if (!OidIsValid(range_typeid))
1924 : : {
1925 : : /* If we don't have a range type yet, use the one we just got */
1926 : 764 : range_typeid = multirange_typelem;
1927 : 764 : range_typelem = get_range_subtype(multirange_typelem);
1928 [ - + ]: 764 : if (!OidIsValid(range_typelem))
1721 akorotkov@postgresql 1929 :UBC 0 : return false; /* should be a range, but isn't */
1930 : : }
1721 akorotkov@postgresql 1931 [ + + ]:CBC 264 : else if (multirange_typelem != range_typeid)
1932 : : {
1933 : : /* otherwise, they better match */
1934 : 152 : return false;
1935 : : }
1936 : : }
1937 : :
1938 : : /* Get the element type based on the range type, if we have one */
1502 tgl@sss.pgh.pa.us 1939 [ + + ]: 31469 : if (OidIsValid(range_typeid))
1940 : : {
1941 : 4775 : range_typelem = get_range_subtype(range_typeid);
1942 [ + + ]: 4775 : if (!OidIsValid(range_typelem))
1943 : 2473 : return false; /* should be a range, but isn't */
1944 : :
1721 akorotkov@postgresql 1945 [ + + ]: 2302 : if (!OidIsValid(elem_typeid))
1946 : : {
1947 : : /*
1948 : : * If we don't have an element type yet, use the one we just got
1949 : : */
1950 : 2101 : elem_typeid = range_typelem;
1951 : : }
1952 [ + + ]: 201 : else if (range_typelem != elem_typeid)
1953 : : {
1954 : : /* otherwise, they better match */
1955 : 88 : return false;
1956 : : }
1957 : : }
1958 : :
5039 tgl@sss.pgh.pa.us 1959 [ + + ]: 28908 : if (have_anynonarray)
1960 : : {
1961 : : /* require the element type to not be an array or domain over array */
1962 [ + + ]: 7536 : if (type_is_array_domain(elem_typeid))
1963 : 141 : return false;
1964 : : }
1965 : :
1966 [ + + ]: 28767 : if (have_anyenum)
1967 : : {
1968 : : /* require the element type to be an enum */
1969 [ + + ]: 1879 : if (!type_is_enum(elem_typeid))
1970 : 1687 : return false;
1971 : : }
1972 : :
1973 : : /* Deduce range type from multirange type, or check that they agree */
1502 1974 [ + + ]: 27080 : if (OidIsValid(anycompatible_multirange_typeid))
1975 : : {
1976 [ + + ]: 48 : if (OidIsValid(anycompatible_range_typeid))
1977 : : {
1978 [ + + ]: 6 : if (anycompatible_multirange_typelem !=
1979 : : anycompatible_range_typeid)
1980 : 3 : return false;
1981 : : }
1982 : : else
1983 : : {
1984 : 42 : anycompatible_range_typeid = anycompatible_multirange_typelem;
1985 : 42 : anycompatible_range_typelem = get_range_subtype(anycompatible_range_typeid);
1986 [ - + ]: 42 : if (!OidIsValid(anycompatible_range_typelem))
1502 tgl@sss.pgh.pa.us 1987 :UBC 0 : return false; /* not a range type */
1988 : : /* collect the subtype for common-supertype choice */
1502 tgl@sss.pgh.pa.us 1989 :CBC 42 : anycompatible_actual_types[n_anycompatible_args++] =
1990 : : anycompatible_range_typelem;
1991 : : }
1992 : : }
1993 : :
1994 : : /* Check matching of ANYCOMPATIBLE-family arguments, if any */
1997 1995 [ + + ]: 27077 : if (n_anycompatible_args > 0)
1996 : : {
1997 : : Oid anycompatible_typeid;
1998 : :
1999 : : anycompatible_typeid =
2000 : 1764 : select_common_type_from_oids(n_anycompatible_args,
2001 : : anycompatible_actual_types,
2002 : : true);
2003 : :
2004 [ + + ]: 1764 : if (!OidIsValid(anycompatible_typeid))
1316 2005 : 324 : return false; /* there's definitely no common supertype */
2006 : :
2007 : : /* We have to verify that the selected type actually works */
2008 [ + + ]: 1440 : if (!verify_common_type_from_oids(anycompatible_typeid,
2009 : : n_anycompatible_args,
2010 : : anycompatible_actual_types))
2011 : 6 : return false;
2012 : :
1997 2013 [ + + ]: 1434 : if (have_anycompatible_nonarray)
2014 : : {
2015 : : /*
2016 : : * require the anycompatible type to not be an array or domain
2017 : : * over array
2018 : : */
2019 [ + + ]: 9 : if (type_is_array_domain(anycompatible_typeid))
2020 : 3 : return false;
2021 : : }
2022 : :
2023 : : /*
2024 : : * The anycompatible type must exactly match the range element type,
2025 : : * if we were able to identify one. This checks compatibility for
2026 : : * anycompatiblemultirange too since that also sets
2027 : : * anycompatible_range_typelem above.
2028 : : */
2029 [ + + + + ]: 1431 : if (OidIsValid(anycompatible_range_typelem) &&
2030 : : anycompatible_range_typelem != anycompatible_typeid)
2031 : 21 : return false;
2032 : : }
2033 : :
2034 : : /* Looks valid */
8187 2035 : 26723 : return true;
2036 : : }
2037 : :
2038 : : /*
2039 : : * enforce_generic_type_consistency()
2040 : : * Make sure a polymorphic function is legally callable, and
2041 : : * deduce actual argument and result types.
2042 : : *
2043 : : * If any polymorphic pseudotype is used in a function's arguments or
2044 : : * return type, we make sure the actual data types are consistent with
2045 : : * each other. The argument consistency rules are shown above for
2046 : : * check_generic_type_consistency().
2047 : : *
2048 : : * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
2049 : : * argument, we attempt to deduce the actual type it should have. If
2050 : : * successful, we alter that position of declared_arg_types[] so that
2051 : : * make_fn_arguments will coerce the literal to the right thing.
2052 : : *
2053 : : * If we have polymorphic arguments of the ANYCOMPATIBLE family,
2054 : : * we similarly alter declared_arg_types[] entries to show the resolved
2055 : : * common supertype, so that make_fn_arguments will coerce the actual
2056 : : * arguments to the proper type.
2057 : : *
2058 : : * Rules are applied to the function's return type (possibly altering it)
2059 : : * if it is declared as a polymorphic type and there is at least one
2060 : : * polymorphic argument type:
2061 : : *
2062 : : * 1) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
2063 : : * argument's actual type as the function's return type.
2064 : : * 2) If return type is ANYARRAY, and any argument is ANYARRAY, use the
2065 : : * argument's actual type as the function's return type.
2066 : : * 3) Similarly, if return type is ANYRANGE or ANYMULTIRANGE, and any
2067 : : * argument is ANYRANGE or ANYMULTIRANGE, use that argument's actual type
2068 : : * (or the corresponding range or multirange type) as the function's return
2069 : : * type.
2070 : : * 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, and there is
2071 : : * at least one ANYELEMENT, ANYARRAY, ANYRANGE, or ANYMULTIRANGE input,
2072 : : * deduce the return type from those inputs, or throw error if we can't.
2073 : : * 5) Otherwise, if return type is ANYRANGE or ANYMULTIRANGE, throw error.
2074 : : * (We have no way to select a specific range type if the arguments don't
2075 : : * include ANYRANGE or ANYMULTIRANGE.)
2076 : : * 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
2077 : : * (alone or in combination with plain ANYELEMENT), we add the extra
2078 : : * condition that the ANYELEMENT type must be an enum.
2079 : : * 7) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
2080 : : * we add the extra condition that the ANYELEMENT type must not be an array.
2081 : : * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
2082 : : * is an extra restriction if not.)
2083 : : * 8) ANYCOMPATIBLE, ANYCOMPATIBLEARRAY, and ANYCOMPATIBLENONARRAY are handled
2084 : : * by resolving the common supertype of those arguments (or their element
2085 : : * types, for array inputs), and then coercing all those arguments to the
2086 : : * common supertype, or the array type over the common supertype for
2087 : : * ANYCOMPATIBLEARRAY.
2088 : : * 9) For ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE, there must be at
2089 : : * least one non-UNKNOWN input matching those arguments, and all such
2090 : : * inputs must be the same range type (or its multirange type, as
2091 : : * appropriate), since we cannot deduce a range type from non-range types.
2092 : : * Furthermore, the range type's subtype is included while choosing the
2093 : : * common supertype for ANYCOMPATIBLE et al, and it must exactly match
2094 : : * that common supertype.
2095 : : *
2096 : : * Domains over arrays or ranges match ANYARRAY or ANYRANGE arguments,
2097 : : * respectively, and are immediately flattened to their base type. (In
2098 : : * particular, if the return type is also ANYARRAY or ANYRANGE, we'll set
2099 : : * it to the base type not the domain type.) The same is true for
2100 : : * ANYMULTIRANGE, ANYCOMPATIBLEARRAY, ANYCOMPATIBLERANGE, and
2101 : : * ANYCOMPATIBLEMULTIRANGE.
2102 : : *
2103 : : * When allow_poly is false, we are not expecting any of the actual_arg_types
2104 : : * to be polymorphic, and we should not return a polymorphic result type
2105 : : * either. When allow_poly is true, it is okay to have polymorphic "actual"
2106 : : * arg types, and we can return a matching polymorphic type as the result.
2107 : : * (This case is currently used only to check compatibility of an aggregate's
2108 : : * declaration with the underlying transfn.)
2109 : : *
2110 : : * A special case is that we could see ANYARRAY as an actual_arg_type even
2111 : : * when allow_poly is false (this is possible only because pg_statistic has
2112 : : * columns shown as anyarray in the catalogs). We allow this to match a
2113 : : * declared ANYARRAY argument, but only if there is no other polymorphic
2114 : : * argument that we would need to match it with, and no need to determine
2115 : : * the element type to infer the result type. Note this means that functions
2116 : : * taking ANYARRAY had better behave sanely if applied to the pg_statistic
2117 : : * columns; they can't just assume that successive inputs are of the same
2118 : : * actual element type. There is no similar logic for ANYCOMPATIBLEARRAY;
2119 : : * there isn't a need for it since there are no catalog columns of that type,
2120 : : * so we won't see it as input. We could consider matching an actual ANYARRAY
2121 : : * input to an ANYCOMPATIBLEARRAY argument, but at present that seems useless
2122 : : * as well, since there's no value in using ANYCOMPATIBLEARRAY unless there's
2123 : : * at least one other ANYCOMPATIBLE-family argument or result.
2124 : : *
2125 : : * Also, if there are no arguments declared to be of polymorphic types,
2126 : : * we'll return the rettype unmodified even if it's polymorphic. This should
2127 : : * never occur for user-declared functions, because CREATE FUNCTION prevents
2128 : : * it. But it does happen for some built-in functions, such as array_in().
2129 : : */
2130 : : Oid
2510 peter_e@gmx.net 2131 : 512642 : enforce_generic_type_consistency(const Oid *actual_arg_types,
2132 : : Oid *declared_arg_types,
2133 : : int nargs,
2134 : : Oid rettype,
2135 : : bool allow_poly)
2136 : : {
1997 tgl@sss.pgh.pa.us 2137 : 512642 : bool have_poly_anycompatible = false;
1999 2138 : 512642 : bool have_poly_unknowns = false;
8187 2139 : 512642 : Oid elem_typeid = InvalidOid;
2140 : 512642 : Oid array_typeid = InvalidOid;
5056 heikki.linnakangas@i 2141 : 512642 : Oid range_typeid = InvalidOid;
1721 akorotkov@postgresql 2142 : 512642 : Oid multirange_typeid = InvalidOid;
1997 tgl@sss.pgh.pa.us 2143 : 512642 : Oid anycompatible_typeid = InvalidOid;
2144 : 512642 : Oid anycompatible_array_typeid = InvalidOid;
2145 : 512642 : Oid anycompatible_range_typeid = InvalidOid;
2146 : 512642 : Oid anycompatible_range_typelem = InvalidOid;
1721 akorotkov@postgresql 2147 : 512642 : Oid anycompatible_multirange_typeid = InvalidOid;
2148 : 512642 : Oid anycompatible_multirange_typelem = InvalidOid;
6667 tgl@sss.pgh.pa.us 2149 : 512642 : bool have_anynonarray = (rettype == ANYNONARRAYOID);
6732 2150 : 512642 : bool have_anyenum = (rettype == ANYENUMOID);
1502 2151 : 512642 : bool have_anymultirange = (rettype == ANYMULTIRANGEOID);
1997 2152 : 512642 : bool have_anycompatible_nonarray = (rettype == ANYCOMPATIBLENONARRAYOID);
2153 : 512642 : bool have_anycompatible_array = (rettype == ANYCOMPATIBLEARRAYOID);
2154 : 512642 : bool have_anycompatible_range = (rettype == ANYCOMPATIBLERANGEOID);
1502 2155 : 512642 : bool have_anycompatible_multirange = (rettype == ANYCOMPATIBLEMULTIRANGEOID);
1997 2156 : 512642 : int n_poly_args = 0; /* this counts all family-1 arguments */
2157 : 512642 : int n_anycompatible_args = 0; /* this counts only non-unknowns */
2158 : : Oid anycompatible_actual_types[FUNC_MAX_ARGS];
2159 : :
2160 : : /*
2161 : : * Loop through the arguments to see if we have any that are polymorphic.
2162 : : * If so, require the actual types to be consistent.
2163 : : */
2164 [ - + ]: 512642 : Assert(nargs <= FUNC_MAX_ARGS);
1999 2165 [ + + ]: 1512596 : for (int j = 0; j < nargs; j++)
2166 : : {
6667 2167 : 999954 : Oid decl_type = declared_arg_types[j];
8069 bruce@momjian.us 2168 : 999954 : Oid actual_type = actual_arg_types[j];
2169 : :
6667 tgl@sss.pgh.pa.us 2170 [ + + + + ]: 999954 : if (decl_type == ANYELEMENTOID ||
2171 [ + + ]: 989478 : decl_type == ANYNONARRAYOID ||
2172 : : decl_type == ANYENUMOID)
2173 : : {
1999 2174 : 10895 : n_poly_args++;
6667 2175 [ + + ]: 10895 : if (decl_type == ANYNONARRAYOID)
2176 : 7333 : have_anynonarray = true;
2177 [ + + ]: 3562 : else if (decl_type == ANYENUMOID)
6732 2178 : 419 : have_anyenum = true;
8187 2179 [ + + ]: 10895 : if (actual_type == UNKNOWNOID)
2180 : : {
1999 2181 : 378 : have_poly_unknowns = true;
8187 2182 : 378 : continue;
2183 : : }
6448 2184 [ + + + + ]: 10517 : if (allow_poly && decl_type == actual_type)
2185 : 88 : continue; /* no new information here */
8187 2186 [ + + - + ]: 10429 : if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
8085 tgl@sss.pgh.pa.us 2187 [ # # ]:UBC 0 : ereport(ERROR,
2188 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2189 : : errmsg("arguments declared \"%s\" are not all alike", "anyelement"),
2190 : : errdetail("%s versus %s",
2191 : : format_type_be(elem_typeid),
2192 : : format_type_be(actual_type))));
8187 tgl@sss.pgh.pa.us 2193 :CBC 10429 : elem_typeid = actual_type;
2194 : : }
6667 2195 [ + + ]: 989059 : else if (decl_type == ANYARRAYOID)
2196 : : {
1999 2197 : 17569 : n_poly_args++;
8187 2198 [ + + ]: 17569 : if (actual_type == UNKNOWNOID)
2199 : : {
1999 2200 : 2254 : have_poly_unknowns = true;
8187 2201 : 2254 : continue;
2202 : : }
6448 2203 [ + + + + ]: 15315 : if (allow_poly && decl_type == actual_type)
2204 : 49 : continue; /* no new information here */
2999 2205 : 15266 : actual_type = getBaseType(actual_type); /* flatten domains */
8187 2206 [ + + - + ]: 15266 : if (OidIsValid(array_typeid) && actual_type != array_typeid)
8085 tgl@sss.pgh.pa.us 2207 [ # # ]:UBC 0 : ereport(ERROR,
2208 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2209 : : errmsg("arguments declared \"%s\" are not all alike", "anyarray"),
2210 : : errdetail("%s versus %s",
2211 : : format_type_be(array_typeid),
2212 : : format_type_be(actual_type))));
8187 tgl@sss.pgh.pa.us 2213 :CBC 15266 : array_typeid = actual_type;
2214 : : }
5056 heikki.linnakangas@i 2215 [ + + ]: 971490 : else if (decl_type == ANYRANGEOID)
2216 : : {
1999 tgl@sss.pgh.pa.us 2217 : 3678 : n_poly_args++;
5056 heikki.linnakangas@i 2218 [ + + ]: 3678 : if (actual_type == UNKNOWNOID)
2219 : : {
1999 tgl@sss.pgh.pa.us 2220 : 402 : have_poly_unknowns = true;
5056 heikki.linnakangas@i 2221 : 402 : continue;
2222 : : }
2223 [ - + - - ]: 3276 : if (allow_poly && decl_type == actual_type)
5056 heikki.linnakangas@i 2224 :UBC 0 : continue; /* no new information here */
2999 tgl@sss.pgh.pa.us 2225 :CBC 3276 : actual_type = getBaseType(actual_type); /* flatten domains */
5056 heikki.linnakangas@i 2226 [ + + - + ]: 3276 : if (OidIsValid(range_typeid) && actual_type != range_typeid)
5056 heikki.linnakangas@i 2227 [ # # ]:UBC 0 : ereport(ERROR,
2228 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2229 : : errmsg("arguments declared \"%s\" are not all alike", "anyrange"),
2230 : : errdetail("%s versus %s",
2231 : : format_type_be(range_typeid),
2232 : : format_type_be(actual_type))));
5056 heikki.linnakangas@i 2233 :CBC 3276 : range_typeid = actual_type;
2234 : : }
1721 akorotkov@postgresql 2235 [ + + ]: 967812 : else if (decl_type == ANYMULTIRANGEOID)
2236 : : {
2237 : 2455 : n_poly_args++;
1502 tgl@sss.pgh.pa.us 2238 : 2455 : have_anymultirange = true;
1721 akorotkov@postgresql 2239 [ + + ]: 2455 : if (actual_type == UNKNOWNOID)
2240 : : {
2241 : 132 : have_poly_unknowns = true;
2242 : 132 : continue;
2243 : : }
2244 [ - + - - ]: 2323 : if (allow_poly && decl_type == actual_type)
1721 akorotkov@postgresql 2245 :UBC 0 : continue; /* no new information here */
1721 akorotkov@postgresql 2246 :CBC 2323 : actual_type = getBaseType(actual_type); /* flatten domains */
2247 [ + + - + ]: 2323 : if (OidIsValid(multirange_typeid) && actual_type != multirange_typeid)
1721 akorotkov@postgresql 2248 [ # # ]:UBC 0 : ereport(ERROR,
2249 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2250 : : errmsg("arguments declared \"%s\" are not all alike", "anymultirange"),
2251 : : errdetail("%s versus %s",
2252 : : format_type_be(multirange_typeid),
2253 : : format_type_be(actual_type))));
1721 akorotkov@postgresql 2254 :CBC 2323 : multirange_typeid = actual_type;
2255 : : }
1997 tgl@sss.pgh.pa.us 2256 [ + + + + ]: 965357 : else if (decl_type == ANYCOMPATIBLEOID ||
2257 : : decl_type == ANYCOMPATIBLENONARRAYOID)
2258 : : {
2259 : 1077 : have_poly_anycompatible = true;
2260 [ + + ]: 1077 : if (decl_type == ANYCOMPATIBLENONARRAYOID)
2261 : 12 : have_anycompatible_nonarray = true;
2262 [ + + ]: 1077 : if (actual_type == UNKNOWNOID)
2263 : 574 : continue;
2264 [ + + + + ]: 503 : if (allow_poly && decl_type == actual_type)
2265 : 4 : continue; /* no new information here */
2266 : : /* collect the actual types of non-unknown COMPATIBLE args */
2267 : 499 : anycompatible_actual_types[n_anycompatible_args++] = actual_type;
2268 : : }
2269 [ + + ]: 964280 : else if (decl_type == ANYCOMPATIBLEARRAYOID)
2270 : : {
2271 : : Oid anycompatible_elem_type;
2272 : :
2273 : 2713 : have_poly_anycompatible = true;
2274 : 2713 : have_anycompatible_array = true;
2275 [ + + ]: 2713 : if (actual_type == UNKNOWNOID)
2276 : 15 : continue;
2277 [ + + + + ]: 2698 : if (allow_poly && decl_type == actual_type)
2278 : 4 : continue; /* no new information here */
2279 : 2694 : actual_type = getBaseType(actual_type); /* flatten domains */
2280 : 2694 : anycompatible_elem_type = get_element_type(actual_type);
2281 [ - + ]: 2694 : if (!OidIsValid(anycompatible_elem_type))
1997 tgl@sss.pgh.pa.us 2282 [ # # ]:UBC 0 : ereport(ERROR,
2283 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2284 : : errmsg("argument declared %s is not an array but type %s",
2285 : : "anycompatiblearray",
2286 : : format_type_be(actual_type))));
2287 : : /* collect the element type for common-supertype choice */
1997 tgl@sss.pgh.pa.us 2288 :CBC 2694 : anycompatible_actual_types[n_anycompatible_args++] = anycompatible_elem_type;
2289 : : }
2290 [ + + ]: 961567 : else if (decl_type == ANYCOMPATIBLERANGEOID)
2291 : : {
2292 : 69 : have_poly_anycompatible = true;
2293 : 69 : have_anycompatible_range = true;
2294 [ + + ]: 69 : if (actual_type == UNKNOWNOID)
2295 : 6 : continue;
2296 [ - + - - ]: 63 : if (allow_poly && decl_type == actual_type)
1997 tgl@sss.pgh.pa.us 2297 :UBC 0 : continue; /* no new information here */
1997 tgl@sss.pgh.pa.us 2298 :CBC 63 : actual_type = getBaseType(actual_type); /* flatten domains */
2299 [ + + ]: 63 : if (OidIsValid(anycompatible_range_typeid))
2300 : : {
2301 : : /* All ANYCOMPATIBLERANGE arguments must be the same type */
2302 [ - + ]: 3 : if (anycompatible_range_typeid != actual_type)
1997 tgl@sss.pgh.pa.us 2303 [ # # ]:UBC 0 : ereport(ERROR,
2304 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2305 : : errmsg("arguments declared \"%s\" are not all alike", "anycompatiblerange"),
2306 : : errdetail("%s versus %s",
2307 : : format_type_be(anycompatible_range_typeid),
2308 : : format_type_be(actual_type))));
2309 : : }
2310 : : else
2311 : : {
1997 tgl@sss.pgh.pa.us 2312 :CBC 60 : anycompatible_range_typeid = actual_type;
2313 : 60 : anycompatible_range_typelem = get_range_subtype(actual_type);
2314 [ - + ]: 60 : if (!OidIsValid(anycompatible_range_typelem))
1997 tgl@sss.pgh.pa.us 2315 [ # # ]:UBC 0 : ereport(ERROR,
2316 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2317 : : errmsg("argument declared %s is not a range type but type %s",
2318 : : "anycompatiblerange",
2319 : : format_type_be(actual_type))));
2320 : : /* collect the subtype for common-supertype choice */
1997 tgl@sss.pgh.pa.us 2321 :CBC 60 : anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
2322 : : }
2323 : : }
1721 akorotkov@postgresql 2324 [ + + ]: 961498 : else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
2325 : : {
2326 : 48 : have_poly_anycompatible = true;
1502 tgl@sss.pgh.pa.us 2327 : 48 : have_anycompatible_multirange = true;
1721 akorotkov@postgresql 2328 [ + + ]: 48 : if (actual_type == UNKNOWNOID)
2329 : 9 : continue;
2330 [ - + - - ]: 39 : if (allow_poly && decl_type == actual_type)
1721 akorotkov@postgresql 2331 :UBC 0 : continue; /* no new information here */
1721 akorotkov@postgresql 2332 :CBC 39 : actual_type = getBaseType(actual_type); /* flatten domains */
2333 [ + + ]: 39 : if (OidIsValid(anycompatible_multirange_typeid))
2334 : : {
2335 : : /* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
2336 [ - + ]: 3 : if (anycompatible_multirange_typeid != actual_type)
1721 akorotkov@postgresql 2337 [ # # ]:UBC 0 : ereport(ERROR,
2338 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2339 : : errmsg("arguments declared \"%s\" are not all alike", "anycompatiblemultirange"),
2340 : : errdetail("%s versus %s",
2341 : : format_type_be(anycompatible_multirange_typeid),
2342 : : format_type_be(actual_type))));
2343 : : }
2344 : : else
2345 : : {
1721 akorotkov@postgresql 2346 :CBC 36 : anycompatible_multirange_typeid = actual_type;
2347 : 36 : anycompatible_multirange_typelem = get_multirange_range(actual_type);
2348 [ - + ]: 36 : if (!OidIsValid(anycompatible_multirange_typelem))
1721 akorotkov@postgresql 2349 [ # # ]:UBC 0 : ereport(ERROR,
2350 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2351 : : errmsg("argument declared %s is not a multirange type but type %s",
2352 : : "anycompatiblemultirange",
2353 : : format_type_be(actual_type))));
2354 : : /* we'll consider the subtype below */
2355 : : }
2356 : : }
2357 : : }
2358 : :
2359 : : /*
2360 : : * Fast Track: if none of the arguments are polymorphic, return the
2361 : : * unmodified rettype. Not our job to resolve it if it's polymorphic.
2362 : : */
1997 tgl@sss.pgh.pa.us 2363 [ + + + + ]:CBC 512642 : if (n_poly_args == 0 && !have_poly_anycompatible)
8187 2364 : 482667 : return rettype;
2365 : :
2366 : : /* Check matching of family-1 polymorphic arguments, if any */
1999 2367 [ + + ]: 29975 : if (n_poly_args)
2368 : : {
2369 : : /* Get the element type based on the array type, if we have one */
2370 [ + + ]: 28038 : if (OidIsValid(array_typeid))
2371 : : {
2372 : : Oid array_typelem;
2373 : :
2374 [ + + ]: 14441 : if (array_typeid == ANYARRAYOID)
2375 : : {
2376 : : /*
2377 : : * Special case for matching ANYARRAY input to an ANYARRAY
2378 : : * argument: allow it iff no other arguments are family-1
2379 : : * polymorphics (otherwise we couldn't be sure whether the
2380 : : * array element type matches up) and the result type doesn't
2381 : : * require us to infer a specific element type.
2382 : : */
2383 [ + - + + ]: 21 : if (n_poly_args != 1 ||
1997 2384 [ + + ]: 9 : (rettype != ANYARRAYOID &&
2385 [ + - + - : 3 : IsPolymorphicTypeFamily1(rettype)))
+ - + - -
+ ]
1999 2386 [ + - ]: 6 : ereport(ERROR,
2387 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2388 : : errmsg("cannot determine element type of \"anyarray\" argument")));
2389 : 15 : array_typelem = ANYELEMENTOID;
2390 : : }
2391 : : else
2392 : : {
2393 : 14420 : array_typelem = get_element_type(array_typeid);
2394 [ - + ]: 14420 : if (!OidIsValid(array_typelem))
1999 tgl@sss.pgh.pa.us 2395 [ # # ]:UBC 0 : ereport(ERROR,
2396 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2397 : : errmsg("argument declared %s is not an array but type %s",
2398 : : "anyarray", format_type_be(array_typeid))));
2399 : : }
2400 : :
1999 tgl@sss.pgh.pa.us 2401 [ + + ]:CBC 14435 : if (!OidIsValid(elem_typeid))
2402 : : {
2403 : : /*
2404 : : * if we don't have an element type yet, use the one we just
2405 : : * got
2406 : : */
2407 : 14394 : elem_typeid = array_typelem;
2408 : : }
2409 [ - + ]: 41 : else if (array_typelem != elem_typeid)
2410 : : {
2411 : : /* otherwise, they better match */
6110 tgl@sss.pgh.pa.us 2412 [ # # ]:UBC 0 : ereport(ERROR,
2413 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2414 : : errmsg("argument declared %s is not consistent with argument declared %s",
2415 : : "anyarray", "anyelement"),
2416 : : errdetail("%s versus %s",
2417 : : format_type_be(array_typeid),
2418 : : format_type_be(elem_typeid))));
2419 : : }
2420 : : }
2421 : :
2422 : : /* Deduce range type from multirange type, or vice versa */
1721 akorotkov@postgresql 2423 [ + + ]:CBC 28032 : if (OidIsValid(multirange_typeid))
2424 : : {
2425 : : Oid multirange_typelem;
2426 : :
2427 : 1732 : multirange_typelem = get_multirange_range(multirange_typeid);
2428 [ - + ]: 1732 : if (!OidIsValid(multirange_typelem))
1721 akorotkov@postgresql 2429 [ # # ]:UBC 0 : ereport(ERROR,
2430 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2431 : : errmsg("argument declared %s is not a multirange type but type %s",
2432 : : "anymultirange",
2433 : : format_type_be(multirange_typeid))));
2434 : :
1721 akorotkov@postgresql 2435 [ + + ]:CBC 1732 : if (!OidIsValid(range_typeid))
2436 : : {
2437 : : /* if we don't have a range type yet, use the one we just got */
2438 : 1101 : range_typeid = multirange_typelem;
2439 : : }
2440 [ - + ]: 631 : else if (multirange_typelem != range_typeid)
2441 : : {
2442 : : /* otherwise, they better match */
1721 akorotkov@postgresql 2443 [ # # ]:UBC 0 : ereport(ERROR,
2444 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2445 : : errmsg("argument declared %s is not consistent with argument declared %s",
2446 : : "anymultirange", "anyrange"),
2447 : : errdetail("%s versus %s",
2448 : : format_type_be(multirange_typeid),
2449 : : format_type_be(range_typeid))));
2450 : : }
2451 : : }
1502 tgl@sss.pgh.pa.us 2452 [ + + + + ]:CBC 26300 : else if (have_anymultirange && OidIsValid(range_typeid))
2453 : : {
2454 : 121 : multirange_typeid = get_range_multirange(range_typeid);
2455 : : /* We'll complain below if that didn't work */
2456 : : }
2457 : :
2458 : : /* Get the element type based on the range type, if we have one */
2459 [ + + ]: 28032 : if (OidIsValid(range_typeid))
2460 : : {
2461 : : Oid range_typelem;
2462 : :
2463 : 3541 : range_typelem = get_range_subtype(range_typeid);
2464 [ - + ]: 3541 : if (!OidIsValid(range_typelem))
1502 tgl@sss.pgh.pa.us 2465 [ # # ]:UBC 0 : ereport(ERROR,
2466 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2467 : : errmsg("argument declared %s is not a range type but type %s",
2468 : : "anyrange",
2469 : : format_type_be(range_typeid))));
2470 : :
1721 akorotkov@postgresql 2471 [ + + ]:CBC 3541 : if (!OidIsValid(elem_typeid))
2472 : : {
2473 : : /*
2474 : : * if we don't have an element type yet, use the one we just
2475 : : * got
2476 : : */
2477 : 3298 : elem_typeid = range_typelem;
2478 : : }
2479 [ - + ]: 243 : else if (range_typelem != elem_typeid)
2480 : : {
2481 : : /* otherwise, they better match */
1721 akorotkov@postgresql 2482 [ # # ]:UBC 0 : ereport(ERROR,
2483 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2484 : : errmsg("argument declared %s is not consistent with argument declared %s",
2485 : : "anyrange", "anyelement"),
2486 : : errdetail("%s versus %s",
2487 : : format_type_be(range_typeid),
2488 : : format_type_be(elem_typeid))));
2489 : : }
2490 : : }
2491 : :
5056 heikki.linnakangas@i 2492 [ + + ]:CBC 28032 : if (!OidIsValid(elem_typeid))
2493 : : {
1999 tgl@sss.pgh.pa.us 2494 [ + + ]: 110 : if (allow_poly)
2495 : : {
2496 : 98 : elem_typeid = ANYELEMENTOID;
2497 : 98 : array_typeid = ANYARRAYOID;
2498 : 98 : range_typeid = ANYRANGEOID;
1721 akorotkov@postgresql 2499 : 98 : multirange_typeid = ANYMULTIRANGEOID;
2500 : : }
2501 : : else
2502 : : {
2503 : : /*
2504 : : * Only way to get here is if all the family-1 polymorphic
2505 : : * arguments have UNKNOWN inputs.
2506 : : */
1999 tgl@sss.pgh.pa.us 2507 [ + - ]: 12 : ereport(ERROR,
2508 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2509 : : errmsg("could not determine polymorphic type because input has type %s",
2510 : : "unknown")));
2511 : : }
2512 : : }
2513 : :
2514 [ + + + - ]: 28020 : if (have_anynonarray && elem_typeid != ANYELEMENTOID)
2515 : : {
2516 : : /*
2517 : : * require the element type to not be an array or domain over
2518 : : * array
2519 : : */
2520 [ - + ]: 7157 : if (type_is_array_domain(elem_typeid))
1999 tgl@sss.pgh.pa.us 2521 [ # # ]:UBC 0 : ereport(ERROR,
2522 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2523 : : errmsg("type matched to anynonarray is an array type: %s",
2524 : : format_type_be(elem_typeid))));
2525 : : }
2526 : :
1999 tgl@sss.pgh.pa.us 2527 [ + + + - ]:CBC 28020 : if (have_anyenum && elem_typeid != ANYELEMENTOID)
2528 : : {
2529 : : /* require the element type to be an enum */
2530 [ - + ]: 286 : if (!type_is_enum(elem_typeid))
1999 tgl@sss.pgh.pa.us 2531 [ # # ]:UBC 0 : ereport(ERROR,
2532 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2533 : : errmsg("type matched to anyenum is not an enum type: %s",
2534 : : format_type_be(elem_typeid))));
2535 : : }
2536 : : }
2537 : :
2538 : : /* Check matching of family-2 polymorphic arguments, if any */
1997 tgl@sss.pgh.pa.us 2539 [ + + ]:CBC 29957 : if (have_poly_anycompatible)
2540 : : {
2541 : : /* Deduce range type from multirange type, or vice versa */
1502 2542 [ + + ]: 1964 : if (OidIsValid(anycompatible_multirange_typeid))
2543 : : {
2544 [ + + ]: 36 : if (OidIsValid(anycompatible_range_typeid))
2545 : : {
2546 [ - + ]: 3 : if (anycompatible_multirange_typelem !=
2547 : : anycompatible_range_typeid)
1502 tgl@sss.pgh.pa.us 2548 [ # # ]:UBC 0 : ereport(ERROR,
2549 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2550 : : errmsg("argument declared %s is not consistent with argument declared %s",
2551 : : "anycompatiblemultirange",
2552 : : "anycompatiblerange"),
2553 : : errdetail("%s versus %s",
2554 : : format_type_be(anycompatible_multirange_typeid),
2555 : : format_type_be(anycompatible_range_typeid))));
2556 : : }
2557 : : else
2558 : : {
1502 tgl@sss.pgh.pa.us 2559 :CBC 33 : anycompatible_range_typeid = anycompatible_multirange_typelem;
2560 : 33 : anycompatible_range_typelem = get_range_subtype(anycompatible_range_typeid);
2561 [ - + ]: 33 : if (!OidIsValid(anycompatible_range_typelem))
1502 tgl@sss.pgh.pa.us 2562 [ # # ]:UBC 0 : ereport(ERROR,
2563 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2564 : : errmsg("argument declared %s is not a multirange type but type %s",
2565 : : "anycompatiblemultirange",
2566 : : format_type_be(anycompatible_multirange_typeid))));
2567 : : /* this enables element type matching check below */
1502 tgl@sss.pgh.pa.us 2568 :CBC 33 : have_anycompatible_range = true;
2569 : : /* collect the subtype for common-supertype choice */
2570 : 33 : anycompatible_actual_types[n_anycompatible_args++] =
2571 : : anycompatible_range_typelem;
2572 : : }
2573 : : }
2574 [ + + + + ]: 1928 : else if (have_anycompatible_multirange &&
2575 : : OidIsValid(anycompatible_range_typeid))
2576 : : {
2577 : 3 : anycompatible_multirange_typeid = get_range_multirange(anycompatible_range_typeid);
2578 : : /* We'll complain below if that didn't work */
2579 : : }
2580 : :
1997 2581 [ + + ]: 1964 : if (n_anycompatible_args > 0)
2582 : : {
2583 : : anycompatible_typeid =
2584 : 1948 : select_common_type_from_oids(n_anycompatible_args,
2585 : : anycompatible_actual_types,
2586 : : false);
2587 : :
2588 : : /* We have to verify that the selected type actually works */
1316 2589 [ - + ]: 1948 : if (!verify_common_type_from_oids(anycompatible_typeid,
2590 : : n_anycompatible_args,
2591 : : anycompatible_actual_types))
1316 tgl@sss.pgh.pa.us 2592 [ # # ]:UBC 0 : ereport(ERROR,
2593 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2594 : : errmsg("arguments of anycompatible family cannot be cast to a common type")));
2595 : :
1997 tgl@sss.pgh.pa.us 2596 [ + + ]:CBC 1948 : if (have_anycompatible_array)
2597 : : {
2598 : 1849 : anycompatible_array_typeid = get_array_type(anycompatible_typeid);
2599 [ - + ]: 1849 : if (!OidIsValid(anycompatible_array_typeid))
1997 tgl@sss.pgh.pa.us 2600 [ # # ]:UBC 0 : ereport(ERROR,
2601 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
2602 : : errmsg("could not find array type for data type %s",
2603 : : format_type_be(anycompatible_typeid))));
2604 : : }
2605 : :
1997 tgl@sss.pgh.pa.us 2606 [ + + ]:CBC 1948 : if (have_anycompatible_range)
2607 : : {
2608 : : /* we can't infer a range type from the others */
2609 [ + + ]: 96 : if (!OidIsValid(anycompatible_range_typeid))
2610 [ + - ]: 3 : ereport(ERROR,
2611 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2612 : : errmsg("could not determine polymorphic type %s because input has type %s",
2613 : : "anycompatiblerange", "unknown")));
2614 : :
2615 : : /*
2616 : : * the anycompatible type must exactly match the range element
2617 : : * type
2618 : : */
2619 [ - + ]: 93 : if (anycompatible_range_typelem != anycompatible_typeid)
1997 tgl@sss.pgh.pa.us 2620 [ # # ]:UBC 0 : ereport(ERROR,
2621 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2622 : : errmsg("anycompatiblerange type %s does not match anycompatible type %s",
2623 : : format_type_be(anycompatible_range_typeid),
2624 : : format_type_be(anycompatible_typeid))));
2625 : : }
2626 : :
1502 tgl@sss.pgh.pa.us 2627 [ + + ]:CBC 1945 : if (have_anycompatible_multirange)
2628 : : {
2629 : : /* we can't infer a multirange type from the others */
2630 [ + + ]: 42 : if (!OidIsValid(anycompatible_multirange_typeid))
2631 [ + - ]: 3 : ereport(ERROR,
2632 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2633 : : errmsg("could not determine polymorphic type %s because input has type %s",
2634 : : "anycompatiblemultirange", "unknown")));
2635 : :
2636 : : /*
2637 : : * the anycompatible type must exactly match the multirange
2638 : : * element type
2639 : : */
2640 [ - + ]: 39 : if (anycompatible_range_typelem != anycompatible_typeid)
1502 tgl@sss.pgh.pa.us 2641 [ # # ]:UBC 0 : ereport(ERROR,
2642 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2643 : : errmsg("anycompatiblemultirange type %s does not match anycompatible type %s",
2644 : : format_type_be(anycompatible_multirange_typeid),
2645 : : format_type_be(anycompatible_typeid))));
2646 : : }
2647 : :
1997 tgl@sss.pgh.pa.us 2648 [ + + ]:CBC 1942 : if (have_anycompatible_nonarray)
2649 : : {
2650 : : /*
2651 : : * require the element type to not be an array or domain over
2652 : : * array
2653 : : */
2654 [ - + ]: 6 : if (type_is_array_domain(anycompatible_typeid))
1997 tgl@sss.pgh.pa.us 2655 [ # # ]:UBC 0 : ereport(ERROR,
2656 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2657 : : errmsg("type matched to anycompatiblenonarray is an array type: %s",
2658 : : format_type_be(anycompatible_typeid))));
2659 : : }
2660 : : }
2661 : : else
2662 : : {
1997 tgl@sss.pgh.pa.us 2663 [ + + ]:CBC 16 : if (allow_poly)
2664 : : {
2665 : 4 : anycompatible_typeid = ANYCOMPATIBLEOID;
2666 : 4 : anycompatible_array_typeid = ANYCOMPATIBLEARRAYOID;
2667 : 4 : anycompatible_range_typeid = ANYCOMPATIBLERANGEOID;
1721 akorotkov@postgresql 2668 : 4 : anycompatible_multirange_typeid = ANYCOMPATIBLEMULTIRANGEOID;
2669 : : }
2670 : : else
2671 : : {
2672 : : /*
2673 : : * Only way to get here is if all the family-2 polymorphic
2674 : : * arguments have UNKNOWN inputs. Resolve to TEXT as
2675 : : * select_common_type() would do. That doesn't license us to
2676 : : * use TEXTRANGE or TEXTMULTIRANGE, though.
2677 : : */
1997 tgl@sss.pgh.pa.us 2678 : 12 : anycompatible_typeid = TEXTOID;
2679 : 12 : anycompatible_array_typeid = TEXTARRAYOID;
2680 [ + + ]: 12 : if (have_anycompatible_range)
2681 [ + - ]: 6 : ereport(ERROR,
2682 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2683 : : errmsg("could not determine polymorphic type %s because input has type %s",
2684 : : "anycompatiblerange", "unknown")));
1502 2685 [ + + ]: 6 : if (have_anycompatible_multirange)
2686 [ + - ]: 3 : ereport(ERROR,
2687 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2688 : : errmsg("could not determine polymorphic type %s because input has type %s",
2689 : : "anycompatiblemultirange", "unknown")));
2690 : : }
2691 : : }
2692 : :
2693 : : /* replace family-2 polymorphic types by selected types */
1997 2694 [ + + ]: 5904 : for (int j = 0; j < nargs; j++)
2695 : : {
2696 : 3955 : Oid decl_type = declared_arg_types[j];
2697 : :
2698 [ + + + + ]: 3955 : if (decl_type == ANYCOMPATIBLEOID ||
2699 : : decl_type == ANYCOMPATIBLENONARRAYOID)
2700 : 1071 : declared_arg_types[j] = anycompatible_typeid;
2701 [ + + ]: 2884 : else if (decl_type == ANYCOMPATIBLEARRAYOID)
2702 : 2713 : declared_arg_types[j] = anycompatible_array_typeid;
2703 [ + + ]: 171 : else if (decl_type == ANYCOMPATIBLERANGEOID)
2704 : 63 : declared_arg_types[j] = anycompatible_range_typeid;
1721 akorotkov@postgresql 2705 [ + + ]: 108 : else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
2706 : 39 : declared_arg_types[j] = anycompatible_multirange_typeid;
2707 : : }
2708 : : }
2709 : :
2710 : : /*
2711 : : * If we had any UNKNOWN inputs for family-1 polymorphic arguments,
2712 : : * re-scan to assign correct types to them.
2713 : : *
2714 : : * Note: we don't have to consider unknown inputs that were matched to
2715 : : * family-2 polymorphic arguments, because we forcibly updated their
2716 : : * declared_arg_types[] positions just above.
2717 : : */
1999 tgl@sss.pgh.pa.us 2718 [ + + ]: 29942 : if (have_poly_unknowns)
2719 : : {
2720 [ + + ]: 9880 : for (int j = 0; j < nargs; j++)
2721 : : {
6667 2722 : 6735 : Oid decl_type = declared_arg_types[j];
8069 bruce@momjian.us 2723 : 6735 : Oid actual_type = actual_arg_types[j];
2724 : :
8187 tgl@sss.pgh.pa.us 2725 [ + + ]: 6735 : if (actual_type != UNKNOWNOID)
2726 : 3259 : continue;
2727 : :
6667 2728 [ + + + + ]: 3476 : if (decl_type == ANYELEMENTOID ||
2729 [ + + ]: 3189 : decl_type == ANYNONARRAYOID ||
2730 : : decl_type == ANYENUMOID)
8187 2731 : 375 : declared_arg_types[j] = elem_typeid;
6667 2732 [ + + ]: 3101 : else if (decl_type == ANYARRAYOID)
2733 : : {
8187 2734 [ + + ]: 2254 : if (!OidIsValid(array_typeid))
2735 : : {
2736 : 15 : array_typeid = get_array_type(elem_typeid);
2737 [ - + ]: 15 : if (!OidIsValid(array_typeid))
8085 tgl@sss.pgh.pa.us 2738 [ # # ]:UBC 0 : ereport(ERROR,
2739 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
2740 : : errmsg("could not find array type for data type %s",
2741 : : format_type_be(elem_typeid))));
2742 : : }
8187 tgl@sss.pgh.pa.us 2743 :CBC 2254 : declared_arg_types[j] = array_typeid;
2744 : : }
5056 heikki.linnakangas@i 2745 [ + + ]: 847 : else if (decl_type == ANYRANGEOID)
2746 : : {
2747 [ - + ]: 399 : if (!OidIsValid(range_typeid))
2748 : : {
2749 : : /* we can't infer a range type from the others */
5056 heikki.linnakangas@i 2750 [ # # ]:UBC 0 : ereport(ERROR,
2751 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2752 : : errmsg("could not determine polymorphic type %s because input has type %s",
2753 : : "anyrange", "unknown")));
2754 : : }
5056 heikki.linnakangas@i 2755 :CBC 399 : declared_arg_types[j] = range_typeid;
2756 : : }
1721 akorotkov@postgresql 2757 [ + + ]: 448 : else if (decl_type == ANYMULTIRANGEOID)
2758 : : {
2759 [ - + ]: 126 : if (!OidIsValid(multirange_typeid))
2760 : : {
2761 : : /* we can't infer a multirange type from the others */
1721 akorotkov@postgresql 2762 [ # # ]:UBC 0 : ereport(ERROR,
2763 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2764 : : errmsg("could not determine polymorphic type %s because input has type %s",
2765 : : "anymultirange", "unknown")));
2766 : : }
1721 akorotkov@postgresql 2767 :CBC 126 : declared_arg_types[j] = multirange_typeid;
2768 : : }
2769 : : }
2770 : : }
2771 : :
2772 : : /* if we return ANYELEMENT use the appropriate argument type */
1999 tgl@sss.pgh.pa.us 2773 [ + + + - ]: 29942 : if (rettype == ANYELEMENTOID ||
2774 [ + + ]: 24388 : rettype == ANYNONARRAYOID ||
2775 : : rettype == ANYENUMOID)
2776 : 5668 : return elem_typeid;
2777 : :
2778 : : /* if we return ANYARRAY use the appropriate argument type */
8187 2779 [ + + ]: 24274 : if (rettype == ANYARRAYOID)
2780 : : {
2781 [ + + ]: 7323 : if (!OidIsValid(array_typeid))
2782 : : {
8109 bruce@momjian.us 2783 : 6724 : array_typeid = get_array_type(elem_typeid);
8187 tgl@sss.pgh.pa.us 2784 [ - + ]: 6724 : if (!OidIsValid(array_typeid))
8085 tgl@sss.pgh.pa.us 2785 [ # # ]:UBC 0 : ereport(ERROR,
2786 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
2787 : : errmsg("could not find array type for data type %s",
2788 : : format_type_be(elem_typeid))));
2789 : : }
8187 tgl@sss.pgh.pa.us 2790 :CBC 7323 : return array_typeid;
2791 : : }
2792 : :
2793 : : /* if we return ANYRANGE use the appropriate argument type */
5056 heikki.linnakangas@i 2794 [ + + ]: 16951 : if (rettype == ANYRANGEOID)
2795 : : {
2796 : : /* this error is unreachable if the function signature is valid: */
2797 [ - + ]: 193 : if (!OidIsValid(range_typeid))
5056 heikki.linnakangas@i 2798 [ # # ]:UBC 0 : ereport(ERROR,
2799 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2800 : : errmsg_internal("could not determine polymorphic type %s because input has type %s",
2801 : : "anyrange", "unknown")));
5056 heikki.linnakangas@i 2802 :CBC 193 : return range_typeid;
2803 : : }
2804 : :
2805 : : /* if we return ANYMULTIRANGE use the appropriate argument type */
1721 akorotkov@postgresql 2806 [ + + ]: 16758 : if (rettype == ANYMULTIRANGEOID)
2807 : : {
2808 : : /* this error is unreachable if the function signature is valid: */
2809 [ - + ]: 406 : if (!OidIsValid(multirange_typeid))
1502 tgl@sss.pgh.pa.us 2810 [ # # ]:UBC 0 : ereport(ERROR,
2811 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2812 : : errmsg_internal("could not determine polymorphic type %s because input has type %s",
2813 : : "anymultirange", "unknown")));
1721 akorotkov@postgresql 2814 :CBC 406 : return multirange_typeid;
2815 : : }
2816 : :
2817 : : /* if we return ANYCOMPATIBLE use the appropriate type */
1997 tgl@sss.pgh.pa.us 2818 [ + + - + ]: 16352 : if (rettype == ANYCOMPATIBLEOID ||
2819 : : rettype == ANYCOMPATIBLENONARRAYOID)
2820 : : {
2821 : : /* this error is unreachable if the function signature is valid: */
2822 [ - + ]: 79 : if (!OidIsValid(anycompatible_typeid))
1997 tgl@sss.pgh.pa.us 2823 [ # # ]:UBC 0 : ereport(ERROR,
2824 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2825 : : errmsg_internal("could not identify anycompatible type")));
1997 tgl@sss.pgh.pa.us 2826 :CBC 79 : return anycompatible_typeid;
2827 : : }
2828 : :
2829 : : /* if we return ANYCOMPATIBLEARRAY use the appropriate type */
2830 [ + + ]: 16273 : if (rettype == ANYCOMPATIBLEARRAYOID)
2831 : : {
2832 : : /* this error is unreachable if the function signature is valid: */
2833 [ - + ]: 1681 : if (!OidIsValid(anycompatible_array_typeid))
1997 tgl@sss.pgh.pa.us 2834 [ # # ]:UBC 0 : ereport(ERROR,
2835 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2836 : : errmsg_internal("could not identify anycompatiblearray type")));
1997 tgl@sss.pgh.pa.us 2837 :CBC 1681 : return anycompatible_array_typeid;
2838 : : }
2839 : :
2840 : : /* if we return ANYCOMPATIBLERANGE use the appropriate argument type */
2841 [ + + ]: 14592 : if (rettype == ANYCOMPATIBLERANGEOID)
2842 : : {
2843 : : /* this error is unreachable if the function signature is valid: */
2844 [ - + ]: 21 : if (!OidIsValid(anycompatible_range_typeid))
1997 tgl@sss.pgh.pa.us 2845 [ # # ]:UBC 0 : ereport(ERROR,
2846 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2847 : : errmsg_internal("could not identify anycompatiblerange type")));
1997 tgl@sss.pgh.pa.us 2848 :CBC 21 : return anycompatible_range_typeid;
2849 : : }
2850 : :
2851 : : /* if we return ANYCOMPATIBLEMULTIRANGE use the appropriate argument type */
1721 akorotkov@postgresql 2852 [ + + ]: 14571 : if (rettype == ANYCOMPATIBLEMULTIRANGEOID)
2853 : : {
2854 : : /* this error is unreachable if the function signature is valid: */
2855 [ - + ]: 15 : if (!OidIsValid(anycompatible_multirange_typeid))
1721 akorotkov@postgresql 2856 [ # # ]:UBC 0 : ereport(ERROR,
2857 : : (errcode(ERRCODE_DATATYPE_MISMATCH),
2858 : : errmsg_internal("could not identify anycompatiblemultirange type")));
1721 akorotkov@postgresql 2859 :CBC 15 : return anycompatible_multirange_typeid;
2860 : : }
2861 : :
2862 : : /* we don't return a generic type; send back the original return type */
8187 tgl@sss.pgh.pa.us 2863 : 14556 : return rettype;
2864 : : }
2865 : :
2866 : : /*
2867 : : * check_valid_polymorphic_signature()
2868 : : * Is a proposed function signature valid per polymorphism rules?
2869 : : *
2870 : : * Returns NULL if the signature is valid (either ret_type is not polymorphic,
2871 : : * or it can be deduced from the given declared argument types). Otherwise,
2872 : : * returns a palloc'd, already translated errdetail string saying why not.
2873 : : */
2874 : : char *
1999 2875 : 20135 : check_valid_polymorphic_signature(Oid ret_type,
2876 : : const Oid *declared_arg_types,
2877 : : int nargs)
2878 : : {
1721 akorotkov@postgresql 2879 [ + + + + ]: 20135 : if (ret_type == ANYRANGEOID || ret_type == ANYMULTIRANGEOID)
2880 : : {
2881 : : /*
2882 : : * ANYRANGE and ANYMULTIRANGE require an ANYRANGE or ANYMULTIRANGE
2883 : : * input, else we can't tell which of several range types with the
2884 : : * same element type to use.
2885 : : */
1999 tgl@sss.pgh.pa.us 2886 [ + + ]: 114 : for (int i = 0; i < nargs; i++)
2887 : : {
1721 akorotkov@postgresql 2888 [ + + ]: 78 : if (declared_arg_types[i] == ANYRANGEOID ||
2889 [ + + ]: 59 : declared_arg_types[i] == ANYMULTIRANGEOID)
1999 tgl@sss.pgh.pa.us 2890 : 38 : return NULL; /* OK */
2891 : : }
1721 akorotkov@postgresql 2892 : 36 : return psprintf(_("A result of type %s requires at least one input of type anyrange or anymultirange."),
2893 : : format_type_be(ret_type));
2894 : : }
2895 [ + + + + ]: 20061 : else if (ret_type == ANYCOMPATIBLERANGEOID || ret_type == ANYCOMPATIBLEMULTIRANGEOID)
2896 : : {
2897 : : /*
2898 : : * ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE require an
2899 : : * ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE input, else we can't
2900 : : * tell which of several range types with the same element type to
2901 : : * use.
2902 : : */
2903 [ + + ]: 72 : for (int i = 0; i < nargs; i++)
2904 : : {
2905 [ + + ]: 51 : if (declared_arg_types[i] == ANYCOMPATIBLERANGEOID ||
2906 [ + + ]: 36 : declared_arg_types[i] == ANYCOMPATIBLEMULTIRANGEOID)
2907 : 24 : return NULL; /* OK */
2908 : : }
2909 : 21 : return psprintf(_("A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange."),
2910 : : format_type_be(ret_type));
2911 : : }
1997 tgl@sss.pgh.pa.us 2912 [ + + + + : 20016 : else if (IsPolymorphicTypeFamily1(ret_type))
+ - + - +
- - + ]
2913 : : {
2914 : : /* Otherwise, any family-1 type can be deduced from any other */
1999 2915 [ + + ]: 640 : for (int i = 0; i < nargs; i++)
2916 : : {
1997 2917 [ + + + + : 583 : if (IsPolymorphicTypeFamily1(declared_arg_types[i]))
+ - + - +
+ + + ]
1999 2918 : 532 : return NULL; /* OK */
2919 : : }
2920 : : /* Keep this list in sync with IsPolymorphicTypeFamily1! */
1721 akorotkov@postgresql 2921 : 57 : return psprintf(_("A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange."),
2922 : : format_type_be(ret_type));
2923 : : }
1997 tgl@sss.pgh.pa.us 2924 [ + + + + : 19427 : else if (IsPolymorphicTypeFamily2(ret_type))
+ - + - -
+ ]
2925 : : {
2926 : : /* Otherwise, any family-2 type can be deduced from any other */
2927 [ + + ]: 118 : for (int i = 0; i < nargs; i++)
2928 : : {
2929 [ + + + + : 115 : if (IsPolymorphicTypeFamily2(declared_arg_types[i]))
+ + + + +
+ ]
2930 : 94 : return NULL; /* OK */
2931 : : }
2932 : : /* Keep this list in sync with IsPolymorphicTypeFamily2! */
1502 2933 : 3 : return psprintf(_("A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange."),
2934 : : format_type_be(ret_type));
2935 : : }
2936 : : else
1999 2937 : 19330 : return NULL; /* OK, ret_type is not polymorphic */
2938 : : }
2939 : :
2940 : : /*
2941 : : * check_valid_internal_signature()
2942 : : * Is a proposed function signature valid per INTERNAL safety rules?
2943 : : *
2944 : : * Returns NULL if OK, or a suitable error message if ret_type is INTERNAL but
2945 : : * none of the declared arg types are. (It's unsafe to create such a function
2946 : : * since it would allow invocation of INTERNAL-consuming functions directly
2947 : : * from SQL.) It's overkill to return the error detail message, since there
2948 : : * is only one possibility, but we do it like this to keep the API similar to
2949 : : * check_valid_polymorphic_signature().
2950 : : */
2951 : : char *
2952 : 19607 : check_valid_internal_signature(Oid ret_type,
2953 : : const Oid *declared_arg_types,
2954 : : int nargs)
2955 : : {
2956 [ + + ]: 19607 : if (ret_type == INTERNALOID)
2957 : : {
2958 [ + - ]: 963 : for (int i = 0; i < nargs; i++)
2959 : : {
2960 [ + + ]: 963 : if (declared_arg_types[i] == ret_type)
2961 : 670 : return NULL; /* OK */
2962 : : }
1999 tgl@sss.pgh.pa.us 2963 :UBC 0 : return pstrdup(_("A result of type internal requires at least one input of type internal."));
2964 : : }
2965 : : else
1999 tgl@sss.pgh.pa.us 2966 :CBC 18937 : return NULL; /* OK, ret_type is not INTERNAL */
2967 : : }
2968 : :
2969 : :
2970 : : /* TypeCategory()
2971 : : * Assign a category to the specified type OID.
2972 : : *
2973 : : * NB: this must not return TYPCATEGORY_INVALID.
2974 : : */
2975 : : TYPCATEGORY
6247 2976 : 92336 : TypeCategory(Oid type)
2977 : : {
2978 : : char typcategory;
2979 : : bool typispreferred;
2980 : :
2981 : 92336 : get_type_category_preferred(type, &typcategory, &typispreferred);
2982 [ - + ]: 92336 : Assert(typcategory != TYPCATEGORY_INVALID);
2983 : 92336 : return (TYPCATEGORY) typcategory;
2984 : : }
2985 : :
2986 : :
2987 : : /* IsPreferredType()
2988 : : * Check if this type is a preferred type for the given category.
2989 : : *
2990 : : * If category is TYPCATEGORY_INVALID, then we'll return true for preferred
2991 : : * types of any category; otherwise, only for preferred types of that
2992 : : * category.
2993 : : */
2994 : : bool
2995 : 16012 : IsPreferredType(TYPCATEGORY category, Oid type)
2996 : : {
2997 : : char typcategory;
2998 : : bool typispreferred;
2999 : :
3000 : 16012 : get_type_category_preferred(type, &typcategory, &typispreferred);
3001 [ + + - + ]: 16012 : if (category == typcategory || category == TYPCATEGORY_INVALID)
3002 : 10390 : return typispreferred;
3003 : : else
8139 3004 : 5622 : return false;
3005 : : }
3006 : :
3007 : :
3008 : : /* IsBinaryCoercible()
3009 : : * Check if srctype is binary-coercible to targettype.
3010 : : *
3011 : : * This notion allows us to cheat and directly exchange values without
3012 : : * going through the trouble of calling a conversion function. Note that
3013 : : * in general, this should only be an implementation shortcut. Before 7.4,
3014 : : * this was also used as a heuristic for resolving overloaded functions and
3015 : : * operators, but that's basically a bad idea.
3016 : : *
3017 : : * As of 7.3, binary coercibility isn't hardwired into the code anymore.
3018 : : * We consider two types binary-coercible if there is an implicitly
3019 : : * invokable, no-function-needed pg_cast entry. Also, a domain is always
3020 : : * binary-coercible to its base type, though *not* vice versa (in the other
3021 : : * direction, one must apply domain constraint checks before accepting the
3022 : : * value as legitimate). We also need to special-case various polymorphic
3023 : : * types.
3024 : : *
3025 : : * This function replaces IsBinaryCompatible(), which was an inherently
3026 : : * symmetric test. Since the pg_cast entries aren't necessarily symmetric,
3027 : : * the order of the operands is now significant.
3028 : : */
3029 : : bool
8389 3030 : 1236506 : IsBinaryCoercible(Oid srctype, Oid targettype)
3031 : : {
3032 : : Oid castoid;
3033 : :
1055 3034 : 1236506 : return IsBinaryCoercibleWithCast(srctype, targettype, &castoid);
3035 : : }
3036 : :
3037 : : /* IsBinaryCoercibleWithCast()
3038 : : * Check if srctype is binary-coercible to targettype.
3039 : : *
3040 : : * This variant also returns the OID of the pg_cast entry if one is involved.
3041 : : * *castoid is set to InvalidOid if no binary-coercible cast exists, or if
3042 : : * there is a hard-wired rule for it rather than a pg_cast entry.
3043 : : */
3044 : : bool
3045 : 1236608 : IsBinaryCoercibleWithCast(Oid srctype, Oid targettype,
3046 : : Oid *castoid)
3047 : : {
3048 : : HeapTuple tuple;
3049 : : Form_pg_cast castForm;
3050 : : bool result;
3051 : :
3052 : 1236608 : *castoid = InvalidOid;
3053 : :
3054 : : /* Fast path if same type */
8389 3055 [ + + ]: 1236608 : if (srctype == targettype)
8406 3056 : 246930 : return true;
3057 : :
3058 : : /* Anything is coercible to ANY or ANYELEMENT or ANYCOMPATIBLE */
1997 3059 [ + + + + : 989678 : if (targettype == ANYOID || targettype == ANYELEMENTOID ||
- + ]
3060 : : targettype == ANYCOMPATIBLEOID)
4275 3061 : 94 : return true;
3062 : :
3063 : : /* If srctype is a domain, reduce to its base type */
8389 3064 [ + - ]: 989584 : if (OidIsValid(srctype))
3065 : 989584 : srctype = getBaseType(srctype);
3066 : :
3067 : : /* Somewhat-fast path for domain -> base type case */
3068 [ + + ]: 989584 : if (srctype == targettype)
8406 3069 : 6 : return true;
3070 : :
3071 : : /* Also accept any array type as coercible to ANY[COMPATIBLE]ARRAY */
1997 3072 [ + + - + ]: 989578 : if (targettype == ANYARRAYOID || targettype == ANYCOMPATIBLEARRAYOID)
5039 3073 [ + + ]: 52444 : if (type_is_array(srctype))
6667 3074 : 2453 : return true;
3075 : :
3076 : : /* Also accept any non-array type as coercible to ANY[COMPATIBLE]NONARRAY */
1997 3077 [ + - - + ]: 987125 : if (targettype == ANYNONARRAYOID || targettype == ANYCOMPATIBLENONARRAYOID)
5039 tgl@sss.pgh.pa.us 3078 [ # # ]:UBC 0 : if (!type_is_array(srctype))
8107 3079 : 0 : return true;
3080 : :
3081 : : /* Also accept any enum type as coercible to ANYENUM */
6732 tgl@sss.pgh.pa.us 3082 [ + + ]:CBC 987125 : if (targettype == ANYENUMOID)
3083 [ + + ]: 48717 : if (type_is_enum(srctype))
3084 : 117 : return true;
3085 : :
3086 : : /* Also accept any range type as coercible to ANY[COMPATIBLE]RANGE */
1997 3087 [ + + - + ]: 987008 : if (targettype == ANYRANGEOID || targettype == ANYCOMPATIBLERANGEOID)
5056 heikki.linnakangas@i 3088 [ + + ]: 12574 : if (type_is_range(srctype))
3089 : 1679 : return true;
3090 : :
3091 : : /* Also, any multirange type is coercible to ANY[COMPATIBLE]MULTIRANGE */
1721 akorotkov@postgresql 3092 [ + + - + ]: 985329 : if (targettype == ANYMULTIRANGEOID || targettype == ANYCOMPATIBLEMULTIRANGEOID)
3093 [ + + ]: 28145 : if (type_is_multirange(srctype))
3094 : 192 : return true;
3095 : :
3096 : : /* Also accept any composite type as coercible to RECORD */
6172 tgl@sss.pgh.pa.us 3097 [ + + ]: 985137 : if (targettype == RECORDOID)
3098 [ + + ]: 10710 : if (ISCOMPLEX(srctype))
3099 : 439 : return true;
3100 : :
3101 : : /* Also accept any composite array type as coercible to RECORD[] */
3102 [ - + ]: 984698 : if (targettype == RECORDARRAYOID)
6172 tgl@sss.pgh.pa.us 3103 [ # # ]:UBC 0 : if (is_complex_array(srctype))
3104 : 0 : return true;
3105 : :
3106 : : /* Else look in pg_cast */
5683 rhaas@postgresql.org 3107 :CBC 984698 : tuple = SearchSysCache2(CASTSOURCETARGET,
3108 : : ObjectIdGetDatum(srctype),
3109 : : ObjectIdGetDatum(targettype));
8406 tgl@sss.pgh.pa.us 3110 [ + + ]: 984698 : if (!HeapTupleIsValid(tuple))
3111 : 793749 : return false; /* no cast */
3112 : 190949 : castForm = (Form_pg_cast) GETSTRUCT(tuple);
3113 : :
5665 heikki.linnakangas@i 3114 [ + + ]: 210280 : result = (castForm->castmethod == COERCION_METHOD_BINARY &&
8389 tgl@sss.pgh.pa.us 3115 [ + + ]: 19331 : castForm->castcontext == COERCION_CODE_IMPLICIT);
3116 : :
1055 3117 [ + + ]: 190949 : if (result)
3118 : 7511 : *castoid = castForm->oid;
3119 : :
8406 3120 : 190949 : ReleaseSysCache(tuple);
3121 : :
3122 : 190949 : return result;
3123 : : }
3124 : :
3125 : :
3126 : : /*
3127 : : * find_coercion_pathway
3128 : : * Look for a coercion pathway between two types.
3129 : : *
3130 : : * Currently, this deals only with scalar-type cases; it does not consider
3131 : : * polymorphic types nor casts between composite types. (Perhaps fold
3132 : : * those in someday?)
3133 : : *
3134 : : * ccontext determines the set of available casts.
3135 : : *
3136 : : * The possible result codes are:
3137 : : * COERCION_PATH_NONE: failed to find any coercion pathway
3138 : : * *funcid is set to InvalidOid
3139 : : * COERCION_PATH_FUNC: apply the coercion function returned in *funcid
3140 : : * COERCION_PATH_RELABELTYPE: binary-compatible cast, no function needed
3141 : : * *funcid is set to InvalidOid
3142 : : * COERCION_PATH_ARRAYCOERCE: need an ArrayCoerceExpr node
3143 : : * *funcid is set to InvalidOid
3144 : : * COERCION_PATH_COERCEVIAIO: need a CoerceViaIO node
3145 : : * *funcid is set to InvalidOid
3146 : : *
3147 : : * Note: COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
3148 : : * needed to do the coercion; if the target is a domain then we may need to
3149 : : * apply domain constraint checking. If you want to check for a zero-effort
3150 : : * conversion then use IsBinaryCoercible().
3151 : : */
3152 : : CoercionPathType
8389 3153 : 681018 : find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
3154 : : CoercionContext ccontext,
3155 : : Oid *funcid)
3156 : : {
6668 3157 : 681018 : CoercionPathType result = COERCION_PATH_NONE;
3158 : : HeapTuple tuple;
3159 : :
8406 3160 : 681018 : *funcid = InvalidOid;
3161 : :
3162 : : /* Perhaps the types are domains; if so, look at their base types */
3163 [ + - ]: 681018 : if (OidIsValid(sourceTypeId))
3164 : 681018 : sourceTypeId = getBaseType(sourceTypeId);
3165 [ + - ]: 681018 : if (OidIsValid(targetTypeId))
3166 : 681018 : targetTypeId = getBaseType(targetTypeId);
3167 : :
3168 : : /* Domains are always coercible to and from their base type */
3169 [ + + ]: 681018 : if (sourceTypeId == targetTypeId)
6668 3170 : 46030 : return COERCION_PATH_RELABELTYPE;
3171 : :
3172 : : /* Look in pg_cast */
5683 rhaas@postgresql.org 3173 : 634988 : tuple = SearchSysCache2(CASTSOURCETARGET,
3174 : : ObjectIdGetDatum(sourceTypeId),
3175 : : ObjectIdGetDatum(targetTypeId));
3176 : :
8451 peter_e@gmx.net 3177 [ + + ]: 634988 : if (HeapTupleIsValid(tuple))
3178 : : {
8406 tgl@sss.pgh.pa.us 3179 : 249762 : Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
3180 : : CoercionContext castcontext;
3181 : :
3182 : : /* convert char value for castcontext to CoercionContext enum */
8389 3183 [ + + + - ]: 249762 : switch (castForm->castcontext)
3184 : : {
3185 : 198856 : case COERCION_CODE_IMPLICIT:
3186 : 198856 : castcontext = COERCION_IMPLICIT;
3187 : 198856 : break;
3188 : 46035 : case COERCION_CODE_ASSIGNMENT:
3189 : 46035 : castcontext = COERCION_ASSIGNMENT;
3190 : 46035 : break;
3191 : 4871 : case COERCION_CODE_EXPLICIT:
3192 : 4871 : castcontext = COERCION_EXPLICIT;
3193 : 4871 : break;
8389 tgl@sss.pgh.pa.us 3194 :UBC 0 : default:
8085 3195 [ # # ]: 0 : elog(ERROR, "unrecognized castcontext: %d",
3196 : : (int) castForm->castcontext);
3197 : : castcontext = 0; /* keep compiler quiet */
3198 : : break;
3199 : : }
3200 : :
3201 : : /* Rely on ordering of enum for correct behavior here */
8389 tgl@sss.pgh.pa.us 3202 [ + + ]:CBC 249762 : if (ccontext >= castcontext)
3203 : : {
6154 heikki.linnakangas@i 3204 [ + + + - ]: 209647 : switch (castForm->castmethod)
3205 : : {
3206 : 76106 : case COERCION_METHOD_FUNCTION:
3207 : 76106 : result = COERCION_PATH_FUNC;
3208 : 76106 : *funcid = castForm->castfunc;
3209 : 76106 : break;
3210 : 350 : case COERCION_METHOD_INOUT:
3211 : 350 : result = COERCION_PATH_COERCEVIAIO;
3212 : 350 : break;
3213 : 133191 : case COERCION_METHOD_BINARY:
3214 : 133191 : result = COERCION_PATH_RELABELTYPE;
3215 : 133191 : break;
6154 heikki.linnakangas@i 3216 :UBC 0 : default:
3217 [ # # ]: 0 : elog(ERROR, "unrecognized castmethod: %d",
3218 : : (int) castForm->castmethod);
3219 : : break;
3220 : : }
3221 : : }
3222 : :
8451 peter_e@gmx.net 3223 :CBC 249762 : ReleaseSysCache(tuple);
3224 : : }
3225 : : else
3226 : : {
3227 : : /*
3228 : : * If there's no pg_cast entry, perhaps we are dealing with a pair of
3229 : : * array types. If so, and if their element types have a conversion
3230 : : * pathway, report that we can coerce with an ArrayCoerceExpr.
3231 : : *
3232 : : * Hack: disallow coercions to oidvector and int2vector, which
3233 : : * otherwise tend to capture coercions that should go to "real" array
3234 : : * types. We want those types to be considered "real" arrays for many
3235 : : * purposes, but not this one. (Also, ArrayCoerceExpr isn't
3236 : : * guaranteed to produce an output that meets the restrictions of
3237 : : * these datatypes, such as being 1-dimensional.)
3238 : : */
6668 tgl@sss.pgh.pa.us 3239 [ + + + - ]: 385226 : if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
3240 : : {
3241 : : Oid targetElem;
3242 : : Oid sourceElem;
3243 : :
3244 [ + + + + ]: 384933 : if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
2898 3245 : 5689 : (sourceElem = get_element_type(sourceTypeId)) != InvalidOid)
3246 : : {
3247 : : CoercionPathType elempathtype;
3248 : : Oid elemfuncid;
3249 : :
6668 3250 : 5103 : elempathtype = find_coercion_pathway(targetElem,
3251 : : sourceElem,
3252 : : ccontext,
3253 : : &elemfuncid);
2898 3254 [ + + ]: 5103 : if (elempathtype != COERCION_PATH_NONE)
3255 : : {
3256 : 5020 : result = COERCION_PATH_ARRAYCOERCE;
3257 : : }
3258 : : }
3259 : : }
3260 : :
3261 : : /*
3262 : : * If we still haven't found a possibility, consider automatic casting
3263 : : * using I/O functions. We allow assignment casts to string types and
3264 : : * explicit casts from string types to be handled this way. (The
3265 : : * CoerceViaIO mechanism is a lot more general than that, but this is
3266 : : * all we want to allow in the absence of a pg_cast entry.) It would
3267 : : * probably be better to insist on explicit casts in both directions,
3268 : : * but this is a compromise to preserve something of the pre-8.3
3269 : : * behavior that many types had implicit (yipes!) casts to text.
3270 : : */
6668 3271 [ + + ]: 385226 : if (result == COERCION_PATH_NONE)
3272 : : {
3273 [ + + + + ]: 405052 : if (ccontext >= COERCION_ASSIGNMENT &&
6247 3274 : 24846 : TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
6668 3275 : 19999 : result = COERCION_PATH_COERCEVIAIO;
3276 [ + + + + ]: 364550 : else if (ccontext >= COERCION_EXPLICIT &&
6247 3277 : 4343 : TypeCategory(sourceTypeId) == TYPCATEGORY_STRING)
6668 3278 : 2784 : result = COERCION_PATH_COERCEVIAIO;
3279 : : }
3280 : : }
3281 : :
3282 : : /*
3283 : : * When parsing PL/pgSQL assignments, allow an I/O cast to be used
3284 : : * whenever no normal coercion is available.
3285 : : */
1706 3286 [ + + + + ]: 634988 : if (result == COERCION_PATH_NONE &&
3287 : : ccontext == COERCION_PLPGSQL)
3288 : 106 : result = COERCION_PATH_COERCEVIAIO;
3289 : :
8406 3290 : 634988 : return result;
3291 : : }
3292 : :
3293 : :
3294 : : /*
3295 : : * find_typmod_coercion_function -- does the given type need length coercion?
3296 : : *
3297 : : * If the target type possesses a pg_cast function from itself to itself,
3298 : : * it must need length coercion.
3299 : : *
3300 : : * "bpchar" (ie, char(N)) and "numeric" are examples of such types.
3301 : : *
3302 : : * If the given type is a varlena array type, we do not look for a coercion
3303 : : * function associated directly with the array type, but instead look for
3304 : : * one associated with the element type. An ArrayCoerceExpr node must be
3305 : : * used to apply such a function. (Note: currently, it's pointless to
3306 : : * return the funcid in this case, because it'll just get looked up again
3307 : : * in the recursive construction of the ArrayCoerceExpr's elemexpr.)
3308 : : *
3309 : : * We use the same result enum as find_coercion_pathway, but the only possible
3310 : : * result codes are:
3311 : : * COERCION_PATH_NONE: no length coercion needed
3312 : : * COERCION_PATH_FUNC: apply the function returned in *funcid
3313 : : * COERCION_PATH_ARRAYCOERCE: apply the function using ArrayCoerceExpr
3314 : : */
3315 : : CoercionPathType
6738 3316 : 9474 : find_typmod_coercion_function(Oid typeId,
3317 : : Oid *funcid)
3318 : : {
3319 : : CoercionPathType result;
3320 : : Type targetType;
3321 : : Form_pg_type typeForm;
3322 : : HeapTuple tuple;
3323 : :
3324 : 9474 : *funcid = InvalidOid;
6668 3325 : 9474 : result = COERCION_PATH_FUNC;
3326 : :
8451 peter_e@gmx.net 3327 : 9474 : targetType = typeidType(typeId);
8389 tgl@sss.pgh.pa.us 3328 : 9474 : typeForm = (Form_pg_type) GETSTRUCT(targetType);
3329 : :
3330 : : /* Check for a "true" array type */
1732 3331 [ + + + - ]: 9474 : if (IsTrueArrayType(typeForm))
3332 : : {
3333 : : /* Yes, switch our attention to the element type */
8389 3334 : 39 : typeId = typeForm->typelem;
6668 3335 : 39 : result = COERCION_PATH_ARRAYCOERCE;
3336 : : }
7752 3337 : 9474 : ReleaseSysCache(targetType);
3338 : :
3339 : : /* Look in pg_cast */
5683 rhaas@postgresql.org 3340 : 9474 : tuple = SearchSysCache2(CASTSOURCETARGET,
3341 : : ObjectIdGetDatum(typeId),
3342 : : ObjectIdGetDatum(typeId));
3343 : :
7752 tgl@sss.pgh.pa.us 3344 [ + + ]: 9474 : if (HeapTupleIsValid(tuple))
3345 : : {
3346 : 9468 : Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
3347 : :
6738 3348 : 9468 : *funcid = castForm->castfunc;
7752 3349 : 9468 : ReleaseSysCache(tuple);
3350 : : }
3351 : :
6668 3352 [ + + ]: 9474 : if (!OidIsValid(*funcid))
3353 : 6 : result = COERCION_PATH_NONE;
3354 : :
3355 : 9474 : return result;
3356 : : }
3357 : :
3358 : : /*
3359 : : * is_complex_array
3360 : : * Is this type an array of composite?
3361 : : *
3362 : : * Note: this will not return true for record[]; check for RECORDARRAYOID
3363 : : * separately if needed.
3364 : : */
3365 : : static bool
6172 3366 : 14 : is_complex_array(Oid typid)
3367 : : {
3368 : 14 : Oid elemtype = get_element_type(typid);
3369 : :
3370 [ + + + - ]: 14 : return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
3371 : : }
3372 : :
3373 : :
3374 : : /*
3375 : : * Check whether reltypeId is the row type of a typed table of type
3376 : : * reloftypeId, or is a domain over such a row type. (This is conceptually
3377 : : * similar to the subtype relationship checked by typeInheritsFrom().)
3378 : : */
3379 : : static bool
5362 peter_e@gmx.net 3380 : 394204 : typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
3381 : : {
2872 tgl@sss.pgh.pa.us 3382 : 394204 : Oid relid = typeOrDomainTypeRelid(reltypeId);
5263 bruce@momjian.us 3383 : 394204 : bool result = false;
3384 : :
5362 peter_e@gmx.net 3385 [ + + ]: 394204 : if (relid)
3386 : : {
3387 : : HeapTuple tp;
3388 : : Form_pg_class reltup;
3389 : :
3390 : 6284 : tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
3391 [ - + ]: 6284 : if (!HeapTupleIsValid(tp))
5362 peter_e@gmx.net 3392 [ # # ]:UBC 0 : elog(ERROR, "cache lookup failed for relation %u", relid);
3393 : :
5362 peter_e@gmx.net 3394 :CBC 6284 : reltup = (Form_pg_class) GETSTRUCT(tp);
3395 [ + + ]: 6284 : if (reltup->reloftype == reloftypeId)
3396 : 6 : result = true;
3397 : :
3398 : 6284 : ReleaseSysCache(tp);
3399 : : }
3400 : :
3401 : 394204 : return result;
3402 : : }
|