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