]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_coerce.c
Get rid of long-since-vestigial Iter node type, in favor of adding a
[postgresql] / src / backend / parser / parse_coerce.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_coerce.c
4  *              handle type coercions/conversions for parser
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.72 2002/05/12 23:43:03 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "catalog/pg_proc.h"
18 #include "nodes/makefuncs.h"
19 #include "optimizer/clauses.h"
20 #include "parser/parse_coerce.h"
21 #include "parser/parse_expr.h"
22 #include "parser/parse_func.h"
23 #include "parser/parse_type.h"
24 #include "utils/builtins.h"
25 #include "utils/lsyscache.h"
26 #include "utils/syscache.h"
27
28
29 Oid                     DemoteType(Oid inType);
30 Oid                     PromoteTypeToNext(Oid inType);
31
32 static Oid      PreferredType(CATEGORY category, Oid type);
33 static Node *build_func_call(Oid funcid, Oid rettype, List *args);
34 static Oid      find_coercion_function(Oid targetTypeId, Oid inputTypeId,
35                                                                    Oid secondArgType, bool isExplicit);
36
37
38 /* coerce_type()
39  * Convert a function argument to a different type.
40  */
41 Node *
42 coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
43                         Oid targetTypeId, int32 atttypmod, bool isExplicit)
44 {
45         Node       *result;
46
47         if (targetTypeId == inputTypeId ||
48                 targetTypeId == InvalidOid ||
49                 node == NULL)
50         {
51                 /* no conversion needed */
52                 result = node;
53         }
54         else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
55         {
56                 /*
57                  * Input is a string constant with previously undetermined type.
58                  * Apply the target type's typinput function to it to produce a
59                  * constant of the target type.
60                  *
61                  * NOTE: this case cannot be folded together with the other
62                  * constant-input case, since the typinput function does not
63                  * necessarily behave the same as a type conversion function. For
64                  * example, int4's typinput function will reject "1.2", whereas
65                  * float-to-int type conversion will round to integer.
66                  *
67                  * XXX if the typinput function is not cachable, we really ought to
68                  * postpone evaluation of the function call until runtime. But
69                  * there is no way to represent a typinput function call as an
70                  * expression tree, because C-string values are not Datums.
71                  */
72                 Const      *con = (Const *) node;
73                 Const      *newcon = makeNode(Const);
74                 Type            targetType = typeidType(targetTypeId);
75
76                 newcon->consttype = targetTypeId;
77                 newcon->constlen = typeLen(targetType);
78                 newcon->constbyval = typeByVal(targetType);
79                 newcon->constisnull = con->constisnull;
80                 newcon->constisset = false;
81
82                 if (!con->constisnull)
83                 {
84                         char       *val = DatumGetCString(DirectFunctionCall1(unknownout,
85                                                                                                            con->constvalue));
86
87                         newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
88                         pfree(val);
89                 }
90
91                 ReleaseSysCache(targetType);
92
93                 result = (Node *) newcon;
94         }
95         else if (IsBinaryCompatible(inputTypeId, targetTypeId))
96         {
97                 /*
98                  * We don't really need to do a conversion, but we do need to
99                  * attach a RelabelType node so that the expression will be seen
100                  * to have the intended type when inspected by higher-level code.
101                  *
102                  * XXX could we label result with exprTypmod(node) instead of
103                  * default -1 typmod, to save a possible length-coercion later?
104                  * Would work if both types have same interpretation of typmod,
105                  * which is likely but not certain.
106                  */
107                 result = (Node *) makeRelabelType(node, targetTypeId, -1);
108         }
109         else if (typeInheritsFrom(inputTypeId, targetTypeId))
110         {
111                 /*
112                  * Input class type is a subclass of target, so nothing to do
113                  * --- except relabel the type.  This is binary compatibility
114                  * for complex types.
115                  */
116                 result = (Node *) makeRelabelType(node, targetTypeId, -1);
117         }
118         else
119         {
120                 /*
121                  * Otherwise, find the appropriate type conversion function
122                  * (caller should have determined that there is one), and generate
123                  * an expression tree representing run-time application of the
124                  * conversion function.
125                  *
126                  * For domains, we use the coercion function for the base type.
127                  */
128                 Oid                     baseTypeId = getBaseType(targetTypeId);
129                 Oid                     funcId;
130
131                 funcId = find_coercion_function(baseTypeId,
132                                                                                 getBaseType(inputTypeId),
133                                                                                 InvalidOid,
134                                                                                 isExplicit);
135                 if (!OidIsValid(funcId))
136                         elog(ERROR, "coerce_type: no conversion function from %s to %s",
137                                  format_type_be(inputTypeId), format_type_be(targetTypeId));
138
139                 result = build_func_call(funcId, baseTypeId, makeList1(node));
140
141                 /* if domain, relabel with domain type ID */
142                 if (targetTypeId != baseTypeId)
143                         result = (Node *) makeRelabelType(result, targetTypeId, -1);
144
145                 /*
146                  * If the input is a constant, apply the type conversion function
147                  * now instead of delaying to runtime.  (We could, of course, just
148                  * leave this to be done during planning/optimization; but it's a
149                  * very frequent special case, and we save cycles in the rewriter
150                  * if we fold the expression now.)
151                  *
152                  * Note that no folding will occur if the conversion function is not
153                  * marked 'iscachable'.
154                  *
155                  * HACK: if constant is NULL, don't fold it here.  This is needed by
156                  * make_subplan(), which calls this routine on placeholder Const
157                  * nodes that mustn't be collapsed.  (It'd be a lot cleaner to
158                  * make a separate node type for that purpose...)
159                  */
160                 if (IsA(node, Const) &&
161                         !((Const *) node)->constisnull)
162                         result = eval_const_expressions(result);
163         }
164
165         return result;
166 }
167
168
169 /* can_coerce_type()
170  * Can input_typeids be coerced to func_typeids?
171  *
172  * There are a few types which are known apriori to be convertible.
173  * We will check for those cases first, and then look for possible
174  * conversion functions.
175  *
176  * We must be told whether this is an implicit or explicit coercion
177  * (explicit being a CAST construct, explicit function call, etc).
178  * We will accept a wider set of coercion cases for an explicit coercion.
179  *
180  * Notes:
181  * This uses the same mechanism as the CAST() SQL construct in gram.y.
182  */
183 bool
184 can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
185                                 bool isExplicit)
186 {
187         int                     i;
188
189         /* run through argument list... */
190         for (i = 0; i < nargs; i++)
191         {
192                 Oid                     inputTypeId = input_typeids[i];
193                 Oid                     targetTypeId = func_typeids[i];
194                 Oid                     funcId;
195
196                 /* no problem if same type */
197                 if (inputTypeId == targetTypeId)
198                         continue;
199
200                 /*
201                  * one of the known-good transparent conversions? then drop
202                  * through...
203                  */
204                 if (IsBinaryCompatible(inputTypeId, targetTypeId))
205                         continue;
206
207                 /* don't know what to do for the output type? then quit... */
208                 if (targetTypeId == InvalidOid)
209                         return false;
210                 /* don't know what to do for the input type? then quit... */
211                 if (inputTypeId == InvalidOid)
212                         return false;
213
214                 /*
215                  * If input is an untyped string constant, assume we can convert
216                  * it to anything except a class type.
217                  */
218                 if (inputTypeId == UNKNOWNOID)
219                 {
220                         if (ISCOMPLEX(targetTypeId))
221                                 return false;
222                         continue;
223                 }
224
225                 /*
226                  * If input is a class type that inherits from target, no problem
227                  */
228                 if (typeInheritsFrom(inputTypeId, targetTypeId))
229                         continue;
230
231                 /* don't choke on references to no-longer-existing types */
232                 if (!typeidIsValid(inputTypeId))
233                         return false;
234                 if (!typeidIsValid(targetTypeId))
235                         return false;
236
237                 /*
238                  * Else, try for run-time conversion using functions: look for a
239                  * single-argument function named with the target type name and
240                  * accepting the source type.
241                  *
242                  * If either type is a domain, use its base type instead.
243                  */
244                 funcId = find_coercion_function(getBaseType(targetTypeId),
245                                                                                 getBaseType(inputTypeId),
246                                                                                 InvalidOid,
247                                                                                 isExplicit);
248                 if (!OidIsValid(funcId))
249                         return false;
250         }
251
252         return true;
253 }
254
255 /* coerce_type_typmod()
256  * Force a value to a particular typmod, if meaningful and possible.
257  *
258  * This is applied to values that are going to be stored in a relation
259  * (where we have an atttypmod for the column) as well as values being
260  * explicitly CASTed (where the typmod comes from the target type spec).
261  *
262  * The caller must have already ensured that the value is of the correct
263  * type, typically by applying coerce_type.
264  *
265  * If the target column type possesses a function named for the type
266  * and having parameter signature (columntype, int4), we assume that
267  * the type requires coercion to its own length and that the said
268  * function should be invoked to do that.
269  *
270  * "bpchar" (ie, char(N)) and "numeric" are examples of such types.
271  */
272 Node *
273 coerce_type_typmod(ParseState *pstate, Node *node,
274                                    Oid targetTypeId, int32 atttypmod)
275 {
276         Oid                     baseTypeId;
277         Oid                     funcId;
278
279         /*
280          * A negative typmod is assumed to mean that no coercion is wanted.
281          */
282         if (atttypmod < 0 || atttypmod == exprTypmod(node))
283                 return node;
284
285         /* If given type is a domain, use base type instead */
286         baseTypeId = getBaseType(targetTypeId);
287
288         /* Note this is always implicit coercion */
289         funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID, false);
290
291         if (OidIsValid(funcId))
292         {
293                 Const      *cons;
294
295                 cons = makeConst(INT4OID,
296                                                  sizeof(int32),
297                                                  Int32GetDatum(atttypmod),
298                                                  false,
299                                                  true,
300                                                  false,
301                                                  false);
302
303                 node = build_func_call(funcId, baseTypeId, makeList2(node, cons));
304
305                 /* relabel if it's domain case */
306                 if (targetTypeId != baseTypeId)
307                         node = (Node *) makeRelabelType(node, targetTypeId, atttypmod);
308         }
309
310         return node;
311 }
312
313
314 /* coerce_to_boolean()
315  *              Coerce an argument of a construct that requires boolean input
316  *              (AND, OR, NOT, etc).  Also check that input is not a set.
317  *
318  * Returns the possibly-transformed node tree.
319  */
320 Node *
321 coerce_to_boolean(Node *node, const char *constructName)
322 {
323         Oid                     inputTypeId = exprType(node);
324         Oid                     targetTypeId;
325
326         if (inputTypeId != BOOLOID)
327         {
328                 targetTypeId = BOOLOID;
329                 if (!can_coerce_type(1, &inputTypeId, &targetTypeId, false))
330                 {
331                         /* translator: first %s is name of a SQL construct, eg WHERE */
332                         elog(ERROR, "Argument of %s must be type boolean, not type %s",
333                                  constructName, format_type_be(inputTypeId));
334                 }
335                 node = coerce_type(NULL, node, inputTypeId, targetTypeId, -1,
336                                                    false);
337         }
338
339         if (expression_returns_set(node))
340         {
341                 /* translator: %s is name of a SQL construct, eg WHERE */
342                 elog(ERROR, "Argument of %s must not be a set function",
343                          constructName);
344         }
345
346         return node;
347 }
348
349
350 /* select_common_type()
351  *              Determine the common supertype of a list of input expression types.
352  *              This is used for determining the output type of CASE and UNION
353  *              constructs.
354  *
355  * typeids is a nonempty integer list of type OIDs.  Note that earlier items
356  * in the list will be preferred if there is doubt.
357  * 'context' is a phrase to use in the error message if we fail to select
358  * a usable type.
359  *
360  * XXX this code is WRONG, since (for example) given the input (int4,int8)
361  * it will select int4, whereas according to SQL92 clause 9.3 the correct
362  * answer is clearly int8.      To fix this we need a notion of a promotion
363  * hierarchy within type categories --- something more complete than
364  * just a single preferred type.
365  */
366 Oid
367 select_common_type(List *typeids, const char *context)
368 {
369         Oid                     ptype;
370         CATEGORY        pcategory;
371         List       *l;
372
373         Assert(typeids != NIL);
374         ptype = (Oid) lfirsti(typeids);
375         pcategory = TypeCategory(ptype);
376         foreach(l, lnext(typeids))
377         {
378                 Oid                     ntype = (Oid) lfirsti(l);
379
380                 /* move on to next one if no new information... */
381                 if ((ntype != InvalidOid) && (ntype != UNKNOWNOID) && (ntype != ptype))
382                 {
383                         if ((ptype == InvalidOid) || ptype == UNKNOWNOID)
384                         {
385                                 /* so far, only nulls so take anything... */
386                                 ptype = ntype;
387                                 pcategory = TypeCategory(ptype);
388                         }
389                         else if (TypeCategory(ntype) != pcategory)
390                         {
391                                 /*
392                                  * both types in different categories? then not much
393                                  * hope...
394                                  */
395                                 elog(ERROR, "%s types \"%s\" and \"%s\" not matched",
396                                   context, typeidTypeName(ptype), typeidTypeName(ntype));
397                         }
398                         else if (IsPreferredType(pcategory, ntype)
399                                          && !IsPreferredType(pcategory, ptype)
400                                          && can_coerce_type(1, &ptype, &ntype, false))
401                         {
402                                 /*
403                                  * new one is preferred and can convert? then take it...
404                                  */
405                                 ptype = ntype;
406                                 pcategory = TypeCategory(ptype);
407                         }
408                 }
409         }
410
411         /*
412          * If all the inputs were UNKNOWN type --- ie, unknown-type literals
413          * --- then resolve as type TEXT.  This situation comes up with
414          * constructs like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END);
415          * SELECT 'foo' UNION SELECT 'bar'; It might seem desirable to leave
416          * the construct's output type as UNKNOWN, but that really doesn't
417          * work, because we'd probably end up needing a runtime coercion from
418          * UNKNOWN to something else, and we usually won't have it.  We need
419          * to coerce the unknown literals while they are still literals, so a
420          * decision has to be made now.
421          */
422         if (ptype == UNKNOWNOID)
423                 ptype = TEXTOID;
424
425         return ptype;
426 }
427
428 /* coerce_to_common_type()
429  *              Coerce an expression to the given type.
430  *
431  * This is used following select_common_type() to coerce the individual
432  * expressions to the desired type.  'context' is a phrase to use in the
433  * error message if we fail to coerce.
434  *
435  * NOTE: pstate may be NULL.
436  */
437 Node *
438 coerce_to_common_type(ParseState *pstate, Node *node,
439                                           Oid targetTypeId,
440                                           const char *context)
441 {
442         Oid                     inputTypeId = exprType(node);
443
444         if (inputTypeId == targetTypeId)
445                 return node;                    /* no work */
446         if (can_coerce_type(1, &inputTypeId, &targetTypeId, false))
447                 node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
448                                                    false);
449         else
450         {
451                 elog(ERROR, "%s unable to convert to type \"%s\"",
452                          context, typeidTypeName(targetTypeId));
453         }
454         return node;
455 }
456
457
458 /* TypeCategory()
459  * Assign a category to the specified OID.
460  * XXX This should be moved to system catalog lookups
461  * to allow for better type extensibility.
462  * - thomas 2001-09-30
463  */
464 CATEGORY
465 TypeCategory(Oid inType)
466 {
467         CATEGORY        result;
468
469         switch (inType)
470         {
471                 case (BOOLOID):
472                         result = BOOLEAN_TYPE;
473                         break;
474
475                 case (CHAROID):
476                 case (NAMEOID):
477                 case (BPCHAROID):
478                 case (VARCHAROID):
479                 case (TEXTOID):
480                         result = STRING_TYPE;
481                         break;
482
483                 case (BITOID):
484                 case (VARBITOID):
485                         result = BITSTRING_TYPE;
486                         break;
487
488                 case (OIDOID):
489                 case (REGPROCOID):
490                 case (REGPROCEDUREOID):
491                 case (REGOPEROID):
492                 case (REGOPERATOROID):
493                 case (REGCLASSOID):
494                 case (REGTYPEOID):
495                 case (INT2OID):
496                 case (INT4OID):
497                 case (INT8OID):
498                 case (FLOAT4OID):
499                 case (FLOAT8OID):
500                 case (NUMERICOID):
501                 case (CASHOID):
502                         result = NUMERIC_TYPE;
503                         break;
504
505                 case (DATEOID):
506                 case (TIMEOID):
507                 case (TIMETZOID):
508                 case (ABSTIMEOID):
509                 case (TIMESTAMPOID):
510                 case (TIMESTAMPTZOID):
511                         result = DATETIME_TYPE;
512                         break;
513
514                 case (RELTIMEOID):
515                 case (TINTERVALOID):
516                 case (INTERVALOID):
517                         result = TIMESPAN_TYPE;
518                         break;
519
520                 case (POINTOID):
521                 case (LSEGOID):
522                 case (PATHOID):
523                 case (BOXOID):
524                 case (POLYGONOID):
525                 case (LINEOID):
526                 case (CIRCLEOID):
527                         result = GEOMETRIC_TYPE;
528                         break;
529
530                 case (INETOID):
531                 case (CIDROID):
532                         result = NETWORK_TYPE;
533                         break;
534
535                 case (UNKNOWNOID):
536                 case (InvalidOid):
537                         result = UNKNOWN_TYPE;
538                         break;
539
540                 default:
541                         result = USER_TYPE;
542                         break;
543         }
544         return result;
545 }       /* TypeCategory() */
546
547
548 /* IsBinaryCompatible()
549  *              Check if two types are binary-compatible.
550  *
551  * This notion allows us to cheat and directly exchange values without
552  * going through the trouble of calling a conversion function.
553  *
554  * XXX This should be moved to system catalog lookups
555  * to allow for better type extensibility.
556  */
557
558 #define TypeIsTextGroup(t) \
559                 ((t) == TEXTOID || \
560                  (t) == BPCHAROID || \
561                  (t) == VARCHAROID)
562
563 /* Notice OidGroup is a subset of Int4GroupA */
564 #define TypeIsOidGroup(t) \
565                 ((t) == OIDOID || \
566                  (t) == REGPROCOID || \
567                  (t) == REGPROCEDUREOID || \
568                  (t) == REGOPEROID || \
569                  (t) == REGOPERATOROID || \
570                  (t) == REGCLASSOID || \
571                  (t) == REGTYPEOID)
572
573 /*
574  * INT4 is binary-compatible with many types, but we don't want to allow
575  * implicit coercion directly between, say, OID and AbsTime.  So we subdivide
576  * the categories.
577  */
578 #define TypeIsInt4GroupA(t) \
579                 ((t) == INT4OID || \
580                  TypeIsOidGroup(t))
581
582 #define TypeIsInt4GroupB(t) \
583                 ((t) == INT4OID || \
584                  (t) == ABSTIMEOID)
585
586 #define TypeIsInt4GroupC(t) \
587                 ((t) == INT4OID || \
588                  (t) == RELTIMEOID)
589
590 #define TypeIsInetGroup(t) \
591                 ((t) == INETOID || \
592                  (t) == CIDROID)
593
594 #define TypeIsBitGroup(t) \
595                 ((t) == BITOID || \
596                  (t) == VARBITOID)
597
598
599 static bool
600 DirectlyBinaryCompatible(Oid type1, Oid type2)
601 {
602         if (type1 == type2)
603                 return true;
604         if (TypeIsTextGroup(type1) && TypeIsTextGroup(type2))
605                 return true;
606         if (TypeIsInt4GroupA(type1) && TypeIsInt4GroupA(type2))
607                 return true;
608         if (TypeIsInt4GroupB(type1) && TypeIsInt4GroupB(type2))
609                 return true;
610         if (TypeIsInt4GroupC(type1) && TypeIsInt4GroupC(type2))
611                 return true;
612         if (TypeIsInetGroup(type1) && TypeIsInetGroup(type2))
613                 return true;
614         if (TypeIsBitGroup(type1) && TypeIsBitGroup(type2))
615                 return true;
616         return false;
617 }
618
619
620 bool
621 IsBinaryCompatible(Oid type1, Oid type2)
622 {
623         if (DirectlyBinaryCompatible(type1, type2))
624                 return true;
625         /*
626          * Perhaps the types are domains; if so, look at their base types
627          */
628         if (OidIsValid(type1))
629                 type1 = getBaseType(type1);
630         if (OidIsValid(type2))
631                 type2 = getBaseType(type2);
632         if (DirectlyBinaryCompatible(type1, type2))
633                 return true;
634         return false;
635 }
636
637
638 /* IsPreferredType()
639  * Check if this type is a preferred type.
640  * XXX This should be moved to system catalog lookups
641  * to allow for better type extensibility.
642  * - thomas 2001-09-30
643  */
644 bool
645 IsPreferredType(CATEGORY category, Oid type)
646 {
647         return (type == PreferredType(category, type));
648 }       /* IsPreferredType() */
649
650
651 /* PreferredType()
652  * Return the preferred type OID for the specified category.
653  * XXX This should be moved to system catalog lookups
654  * to allow for better type extensibility.
655  * - thomas 2001-09-30
656  */
657 static Oid
658 PreferredType(CATEGORY category, Oid type)
659 {
660         Oid                     result;
661
662         switch (category)
663         {
664                 case (BOOLEAN_TYPE):
665                         result = BOOLOID;
666                         break;
667
668                 case (STRING_TYPE):
669                         result = TEXTOID;
670                         break;
671
672                 case (BITSTRING_TYPE):
673                         result = VARBITOID;
674                         break;
675
676                 case (NUMERIC_TYPE):
677                         if (TypeIsOidGroup(type))
678                                 result = OIDOID;
679                         else if (type == NUMERICOID)
680                                 result = NUMERICOID;
681                         else
682                                 result = FLOAT8OID;
683                         break;
684
685                 case (DATETIME_TYPE):
686                         if (type == DATEOID)
687                                 result = TIMESTAMPOID;
688                         else
689                                 result = TIMESTAMPTZOID;
690                         break;
691
692                 case (TIMESPAN_TYPE):
693                         result = INTERVALOID;
694                         break;
695
696                 case (NETWORK_TYPE):
697                         result = INETOID;
698                         break;
699
700                 case (GEOMETRIC_TYPE):
701                 case (USER_TYPE):
702                         result = type;
703                         break;
704
705                 default:
706                         result = UNKNOWNOID;
707                         break;
708         }
709         return result;
710 }       /* PreferredType() */
711
712 /*
713  * find_coercion_function
714  *              Look for a coercion function between two types.
715  *
716  * A coercion function must be named after (the internal name of) its
717  * result type, and must accept exactly the specified input type.  We
718  * also require it to be defined in the same namespace as its result type.
719  * Furthermore, unless we are doing explicit coercion the function must
720  * be marked as usable for implicit coercion --- this allows coercion
721  * functions to be provided that aren't implicitly invokable.
722  *
723  * This routine is also used to look for length-coercion functions, which
724  * are similar but accept a second argument.  secondArgType is the type
725  * of the second argument (normally INT4OID), or InvalidOid if we are
726  * looking for a regular coercion function.
727  *
728  * If a function is found, return its pg_proc OID; else return InvalidOid.
729  */
730 static Oid
731 find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType,
732                                            bool isExplicit)
733 {
734         Oid                     funcid = InvalidOid;
735         Type            targetType;
736         char       *typname;
737         Oid                     typnamespace;
738         Oid                     oid_array[FUNC_MAX_ARGS];
739         int                     nargs;
740         HeapTuple       ftup;
741
742         targetType = typeidType(targetTypeId);
743         typname = NameStr(((Form_pg_type) GETSTRUCT(targetType))->typname);
744         typnamespace = ((Form_pg_type) GETSTRUCT(targetType))->typnamespace;
745
746         MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
747         oid_array[0] = inputTypeId;
748         if (OidIsValid(secondArgType))
749         {
750                 oid_array[1] = secondArgType;
751                 nargs = 2;
752         }
753         else
754                 nargs = 1;
755
756         ftup = SearchSysCache(PROCNAMENSP,
757                                                   CStringGetDatum(typname),
758                                                   Int16GetDatum(nargs),
759                                                   PointerGetDatum(oid_array),
760                                                   ObjectIdGetDatum(typnamespace));
761         if (HeapTupleIsValid(ftup))
762         {
763                 Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
764
765                 /* Make sure the function's result type is as expected */
766                 if (pform->prorettype == targetTypeId && !pform->proretset &&
767                         !pform->proisagg)
768                 {
769                         /* If needed, make sure it can be invoked implicitly */
770                         if (isExplicit || pform->proimplicit)
771                         {
772                                 /* Okay to use it */
773                                 funcid = ftup->t_data->t_oid;
774                         }
775                 }
776                 ReleaseSysCache(ftup);
777         }
778
779         ReleaseSysCache(targetType);
780         return funcid;
781 }
782
783 /*
784  * Build an expression tree representing a function call.
785  *
786  * The argument expressions must have been transformed already.
787  */
788 static Node *
789 build_func_call(Oid funcid, Oid rettype, List *args)
790 {
791         Func       *funcnode;
792         Expr       *expr;
793
794         funcnode = makeNode(Func);
795         funcnode->funcid = funcid;
796         funcnode->funcresulttype = rettype;
797         funcnode->funcretset = false; /* only possible case here */
798         funcnode->func_fcache = NULL;
799
800         expr = makeNode(Expr);
801         expr->typeOid = rettype;
802         expr->opType = FUNC_EXPR;
803         expr->oper = (Node *) funcnode;
804         expr->args = args;
805
806         return (Node *) expr;
807 }