]> granicus.if.org Git - postgresql/blob - src/backend/utils/fmgr/funcapi.c
Fast ALTER TABLE ADD COLUMN with a non-NULL default
[postgresql] / src / backend / utils / fmgr / funcapi.c
1 /*-------------------------------------------------------------------------
2  *
3  * funcapi.c
4  *        Utility and convenience functions for fmgr functions that return
5  *        sets and/or composite types, or deal with VARIADIC inputs.
6  *
7  * Copyright (c) 2002-2018, PostgreSQL Global Development Group
8  *
9  * IDENTIFICATION
10  *        src/backend/utils/fmgr/funcapi.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include "access/htup_details.h"
17 #include "catalog/namespace.h"
18 #include "catalog/pg_proc.h"
19 #include "catalog/pg_type.h"
20 #include "funcapi.h"
21 #include "nodes/nodeFuncs.h"
22 #include "parser/parse_coerce.h"
23 #include "utils/array.h"
24 #include "utils/builtins.h"
25 #include "utils/lsyscache.h"
26 #include "utils/memutils.h"
27 #include "utils/regproc.h"
28 #include "utils/rel.h"
29 #include "utils/syscache.h"
30 #include "utils/typcache.h"
31
32
33 static void shutdown_MultiFuncCall(Datum arg);
34 static TypeFuncClass internal_get_result_type(Oid funcid,
35                                                  Node *call_expr,
36                                                  ReturnSetInfo *rsinfo,
37                                                  Oid *resultTypeId,
38                                                  TupleDesc *resultTupleDesc);
39 static bool resolve_polymorphic_tupdesc(TupleDesc tupdesc,
40                                                         oidvector *declared_args,
41                                                         Node *call_expr);
42 static TypeFuncClass get_type_func_class(Oid typid, Oid *base_typeid);
43
44
45 /*
46  * init_MultiFuncCall
47  * Create an empty FuncCallContext data structure
48  * and do some other basic Multi-function call setup
49  * and error checking
50  */
51 FuncCallContext *
52 init_MultiFuncCall(PG_FUNCTION_ARGS)
53 {
54         FuncCallContext *retval;
55
56         /*
57          * Bail if we're called in the wrong context
58          */
59         if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
60                 ereport(ERROR,
61                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
62                                  errmsg("set-valued function called in context that cannot accept a set")));
63
64         if (fcinfo->flinfo->fn_extra == NULL)
65         {
66                 /*
67                  * First call
68                  */
69                 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
70                 MemoryContext multi_call_ctx;
71
72                 /*
73                  * Create a suitably long-lived context to hold cross-call data
74                  */
75                 multi_call_ctx = AllocSetContextCreate(fcinfo->flinfo->fn_mcxt,
76                                                                                            "SRF multi-call context",
77                                                                                            ALLOCSET_SMALL_SIZES);
78
79                 /*
80                  * Allocate suitably long-lived space and zero it
81                  */
82                 retval = (FuncCallContext *)
83                         MemoryContextAllocZero(multi_call_ctx,
84                                                                    sizeof(FuncCallContext));
85
86                 /*
87                  * initialize the elements
88                  */
89                 retval->call_cntr = 0;
90                 retval->max_calls = 0;
91                 retval->slot = NULL;
92                 retval->user_fctx = NULL;
93                 retval->attinmeta = NULL;
94                 retval->tuple_desc = NULL;
95                 retval->multi_call_memory_ctx = multi_call_ctx;
96
97                 /*
98                  * save the pointer for cross-call use
99                  */
100                 fcinfo->flinfo->fn_extra = retval;
101
102                 /*
103                  * Ensure we will get shut down cleanly if the exprcontext is not run
104                  * to completion.
105                  */
106                 RegisterExprContextCallback(rsi->econtext,
107                                                                         shutdown_MultiFuncCall,
108                                                                         PointerGetDatum(fcinfo->flinfo));
109         }
110         else
111         {
112                 /* second and subsequent calls */
113                 elog(ERROR, "init_MultiFuncCall cannot be called more than once");
114
115                 /* never reached, but keep compiler happy */
116                 retval = NULL;
117         }
118
119         return retval;
120 }
121
122 /*
123  * per_MultiFuncCall
124  *
125  * Do Multi-function per-call setup
126  */
127 FuncCallContext *
128 per_MultiFuncCall(PG_FUNCTION_ARGS)
129 {
130         FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
131
132         /*
133          * Clear the TupleTableSlot, if present.  This is for safety's sake: the
134          * Slot will be in a long-lived context (it better be, if the
135          * FuncCallContext is pointing to it), but in most usage patterns the
136          * tuples stored in it will be in the function's per-tuple context. So at
137          * the beginning of each call, the Slot will hold a dangling pointer to an
138          * already-recycled tuple.  We clear it out here.
139          *
140          * Note: use of retval->slot is obsolete as of 8.0, and we expect that it
141          * will always be NULL.  This is just here for backwards compatibility in
142          * case someone creates a slot anyway.
143          */
144         if (retval->slot != NULL)
145                 ExecClearTuple(retval->slot);
146
147         return retval;
148 }
149
150 /*
151  * end_MultiFuncCall
152  * Clean up after init_MultiFuncCall
153  */
154 void
155 end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
156 {
157         ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
158
159         /* Deregister the shutdown callback */
160         UnregisterExprContextCallback(rsi->econtext,
161                                                                   shutdown_MultiFuncCall,
162                                                                   PointerGetDatum(fcinfo->flinfo));
163
164         /* But use it to do the real work */
165         shutdown_MultiFuncCall(PointerGetDatum(fcinfo->flinfo));
166 }
167
168 /*
169  * shutdown_MultiFuncCall
170  * Shutdown function to clean up after init_MultiFuncCall
171  */
172 static void
173 shutdown_MultiFuncCall(Datum arg)
174 {
175         FmgrInfo   *flinfo = (FmgrInfo *) DatumGetPointer(arg);
176         FuncCallContext *funcctx = (FuncCallContext *) flinfo->fn_extra;
177
178         /* unbind from flinfo */
179         flinfo->fn_extra = NULL;
180
181         /*
182          * Delete context that holds all multi-call data, including the
183          * FuncCallContext itself
184          */
185         MemoryContextDelete(funcctx->multi_call_memory_ctx);
186 }
187
188
189 /*
190  * get_call_result_type
191  *              Given a function's call info record, determine the kind of datatype
192  *              it is supposed to return.  If resultTypeId isn't NULL, *resultTypeId
193  *              receives the actual datatype OID (this is mainly useful for scalar
194  *              result types).  If resultTupleDesc isn't NULL, *resultTupleDesc
195  *              receives a pointer to a TupleDesc when the result is of a composite
196  *              type, or NULL when it's a scalar result.
197  *
198  * One hard case that this handles is resolution of actual rowtypes for
199  * functions returning RECORD (from either the function's OUT parameter
200  * list, or a ReturnSetInfo context node).  TYPEFUNC_RECORD is returned
201  * only when we couldn't resolve the actual rowtype for lack of information.
202  *
203  * The other hard case that this handles is resolution of polymorphism.
204  * We will never return polymorphic pseudotypes (ANYELEMENT etc), either
205  * as a scalar result type or as a component of a rowtype.
206  *
207  * This function is relatively expensive --- in a function returning set,
208  * try to call it only the first time through.
209  */
210 TypeFuncClass
211 get_call_result_type(FunctionCallInfo fcinfo,
212                                          Oid *resultTypeId,
213                                          TupleDesc *resultTupleDesc)
214 {
215         return internal_get_result_type(fcinfo->flinfo->fn_oid,
216                                                                         fcinfo->flinfo->fn_expr,
217                                                                         (ReturnSetInfo *) fcinfo->resultinfo,
218                                                                         resultTypeId,
219                                                                         resultTupleDesc);
220 }
221
222 /*
223  * get_expr_result_type
224  *              As above, but work from a calling expression node tree
225  */
226 TypeFuncClass
227 get_expr_result_type(Node *expr,
228                                          Oid *resultTypeId,
229                                          TupleDesc *resultTupleDesc)
230 {
231         TypeFuncClass result;
232
233         if (expr && IsA(expr, FuncExpr))
234                 result = internal_get_result_type(((FuncExpr *) expr)->funcid,
235                                                                                   expr,
236                                                                                   NULL,
237                                                                                   resultTypeId,
238                                                                                   resultTupleDesc);
239         else if (expr && IsA(expr, OpExpr))
240                 result = internal_get_result_type(get_opcode(((OpExpr *) expr)->opno),
241                                                                                   expr,
242                                                                                   NULL,
243                                                                                   resultTypeId,
244                                                                                   resultTupleDesc);
245         else
246         {
247                 /* handle as a generic expression; no chance to resolve RECORD */
248                 Oid                     typid = exprType(expr);
249                 Oid                     base_typid;
250
251                 if (resultTypeId)
252                         *resultTypeId = typid;
253                 if (resultTupleDesc)
254                         *resultTupleDesc = NULL;
255                 result = get_type_func_class(typid, &base_typid);
256                 if ((result == TYPEFUNC_COMPOSITE ||
257                          result == TYPEFUNC_COMPOSITE_DOMAIN) &&
258                         resultTupleDesc)
259                         *resultTupleDesc = lookup_rowtype_tupdesc_copy(base_typid, -1);
260         }
261
262         return result;
263 }
264
265 /*
266  * get_func_result_type
267  *              As above, but work from a function's OID only
268  *
269  * This will not be able to resolve pure-RECORD results nor polymorphism.
270  */
271 TypeFuncClass
272 get_func_result_type(Oid functionId,
273                                          Oid *resultTypeId,
274                                          TupleDesc *resultTupleDesc)
275 {
276         return internal_get_result_type(functionId,
277                                                                         NULL,
278                                                                         NULL,
279                                                                         resultTypeId,
280                                                                         resultTupleDesc);
281 }
282
283 /*
284  * internal_get_result_type -- workhorse code implementing all the above
285  *
286  * funcid must always be supplied.  call_expr and rsinfo can be NULL if not
287  * available.  We will return TYPEFUNC_RECORD, and store NULL into
288  * *resultTupleDesc, if we cannot deduce the complete result rowtype from
289  * the available information.
290  */
291 static TypeFuncClass
292 internal_get_result_type(Oid funcid,
293                                                  Node *call_expr,
294                                                  ReturnSetInfo *rsinfo,
295                                                  Oid *resultTypeId,
296                                                  TupleDesc *resultTupleDesc)
297 {
298         TypeFuncClass result;
299         HeapTuple       tp;
300         Form_pg_proc procform;
301         Oid                     rettype;
302         Oid                     base_rettype;
303         TupleDesc       tupdesc;
304
305         /* First fetch the function's pg_proc row to inspect its rettype */
306         tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
307         if (!HeapTupleIsValid(tp))
308                 elog(ERROR, "cache lookup failed for function %u", funcid);
309         procform = (Form_pg_proc) GETSTRUCT(tp);
310
311         rettype = procform->prorettype;
312
313         /* Check for OUT parameters defining a RECORD result */
314         tupdesc = build_function_result_tupdesc_t(tp);
315         if (tupdesc)
316         {
317                 /*
318                  * It has OUT parameters, so it's basically like a regular composite
319                  * type, except we have to be able to resolve any polymorphic OUT
320                  * parameters.
321                  */
322                 if (resultTypeId)
323                         *resultTypeId = rettype;
324
325                 if (resolve_polymorphic_tupdesc(tupdesc,
326                                                                                 &procform->proargtypes,
327                                                                                 call_expr))
328                 {
329                         if (tupdesc->tdtypeid == RECORDOID &&
330                                 tupdesc->tdtypmod < 0)
331                                 assign_record_type_typmod(tupdesc);
332                         if (resultTupleDesc)
333                                 *resultTupleDesc = tupdesc;
334                         result = TYPEFUNC_COMPOSITE;
335                 }
336                 else
337                 {
338                         if (resultTupleDesc)
339                                 *resultTupleDesc = NULL;
340                         result = TYPEFUNC_RECORD;
341                 }
342
343                 ReleaseSysCache(tp);
344
345                 return result;
346         }
347
348         /*
349          * If scalar polymorphic result, try to resolve it.
350          */
351         if (IsPolymorphicType(rettype))
352         {
353                 Oid                     newrettype = exprType(call_expr);
354
355                 if (newrettype == InvalidOid)   /* this probably should not happen */
356                         ereport(ERROR,
357                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
358                                          errmsg("could not determine actual result type for function \"%s\" declared to return type %s",
359                                                         NameStr(procform->proname),
360                                                         format_type_be(rettype))));
361                 rettype = newrettype;
362         }
363
364         if (resultTypeId)
365                 *resultTypeId = rettype;
366         if (resultTupleDesc)
367                 *resultTupleDesc = NULL;        /* default result */
368
369         /* Classify the result type */
370         result = get_type_func_class(rettype, &base_rettype);
371         switch (result)
372         {
373                 case TYPEFUNC_COMPOSITE:
374                 case TYPEFUNC_COMPOSITE_DOMAIN:
375                         if (resultTupleDesc)
376                                 *resultTupleDesc = lookup_rowtype_tupdesc_copy(base_rettype, -1);
377                         /* Named composite types can't have any polymorphic columns */
378                         break;
379                 case TYPEFUNC_SCALAR:
380                         break;
381                 case TYPEFUNC_RECORD:
382                         /* We must get the tupledesc from call context */
383                         if (rsinfo && IsA(rsinfo, ReturnSetInfo) &&
384                                 rsinfo->expectedDesc != NULL)
385                         {
386                                 result = TYPEFUNC_COMPOSITE;
387                                 if (resultTupleDesc)
388                                         *resultTupleDesc = rsinfo->expectedDesc;
389                                 /* Assume no polymorphic columns here, either */
390                         }
391                         break;
392                 default:
393                         break;
394         }
395
396         ReleaseSysCache(tp);
397
398         return result;
399 }
400
401 /*
402  * get_expr_result_tupdesc
403  *              Get a tupdesc describing the result of a composite-valued expression
404  *
405  * If expression is not composite or rowtype can't be determined, returns NULL
406  * if noError is true, else throws error.
407  *
408  * This is a simpler version of get_expr_result_type() for use when the caller
409  * is only interested in determinate rowtype results.
410  */
411 TupleDesc
412 get_expr_result_tupdesc(Node *expr, bool noError)
413 {
414         TupleDesc       tupleDesc;
415         TypeFuncClass functypclass;
416
417         functypclass = get_expr_result_type(expr, NULL, &tupleDesc);
418
419         if (functypclass == TYPEFUNC_COMPOSITE ||
420                 functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
421                 return tupleDesc;
422
423         if (!noError)
424         {
425                 Oid                     exprTypeId = exprType(expr);
426
427                 if (exprTypeId != RECORDOID)
428                         ereport(ERROR,
429                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
430                                          errmsg("type %s is not composite",
431                                                         format_type_be(exprTypeId))));
432                 else
433                         ereport(ERROR,
434                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
435                                          errmsg("record type has not been registered")));
436         }
437
438         return NULL;
439 }
440
441 /*
442  * Given the result tuple descriptor for a function with OUT parameters,
443  * replace any polymorphic columns (ANYELEMENT etc) with correct data types
444  * deduced from the input arguments. Returns true if able to deduce all types,
445  * false if not.
446  */
447 static bool
448 resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
449                                                         Node *call_expr)
450 {
451         int                     natts = tupdesc->natts;
452         int                     nargs = declared_args->dim1;
453         bool            have_anyelement_result = false;
454         bool            have_anyarray_result = false;
455         bool            have_anyrange_result = false;
456         bool            have_anynonarray = false;
457         bool            have_anyenum = false;
458         Oid                     anyelement_type = InvalidOid;
459         Oid                     anyarray_type = InvalidOid;
460         Oid                     anyrange_type = InvalidOid;
461         Oid                     anycollation = InvalidOid;
462         int                     i;
463
464         /* See if there are any polymorphic outputs; quick out if not */
465         for (i = 0; i < natts; i++)
466         {
467                 switch (TupleDescAttr(tupdesc, i)->atttypid)
468                 {
469                         case ANYELEMENTOID:
470                                 have_anyelement_result = true;
471                                 break;
472                         case ANYARRAYOID:
473                                 have_anyarray_result = true;
474                                 break;
475                         case ANYNONARRAYOID:
476                                 have_anyelement_result = true;
477                                 have_anynonarray = true;
478                                 break;
479                         case ANYENUMOID:
480                                 have_anyelement_result = true;
481                                 have_anyenum = true;
482                                 break;
483                         case ANYRANGEOID:
484                                 have_anyrange_result = true;
485                                 break;
486                         default:
487                                 break;
488                 }
489         }
490         if (!have_anyelement_result && !have_anyarray_result &&
491                 !have_anyrange_result)
492                 return true;
493
494         /*
495          * Otherwise, extract actual datatype(s) from input arguments.  (We assume
496          * the parser already validated consistency of the arguments.)
497          */
498         if (!call_expr)
499                 return false;                   /* no hope */
500
501         for (i = 0; i < nargs; i++)
502         {
503                 switch (declared_args->values[i])
504                 {
505                         case ANYELEMENTOID:
506                         case ANYNONARRAYOID:
507                         case ANYENUMOID:
508                                 if (!OidIsValid(anyelement_type))
509                                         anyelement_type = get_call_expr_argtype(call_expr, i);
510                                 break;
511                         case ANYARRAYOID:
512                                 if (!OidIsValid(anyarray_type))
513                                         anyarray_type = get_call_expr_argtype(call_expr, i);
514                                 break;
515                         case ANYRANGEOID:
516                                 if (!OidIsValid(anyrange_type))
517                                         anyrange_type = get_call_expr_argtype(call_expr, i);
518                                 break;
519                         default:
520                                 break;
521                 }
522         }
523
524         /* If nothing found, parser messed up */
525         if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type) &&
526                 !OidIsValid(anyrange_type))
527                 return false;
528
529         /* If needed, deduce one polymorphic type from others */
530         if (have_anyelement_result && !OidIsValid(anyelement_type))
531         {
532                 if (OidIsValid(anyarray_type))
533                         anyelement_type = resolve_generic_type(ANYELEMENTOID,
534                                                                                                    anyarray_type,
535                                                                                                    ANYARRAYOID);
536                 if (OidIsValid(anyrange_type))
537                 {
538                         Oid                     subtype = resolve_generic_type(ANYELEMENTOID,
539                                                                                                            anyrange_type,
540                                                                                                            ANYRANGEOID);
541
542                         /* check for inconsistent array and range results */
543                         if (OidIsValid(anyelement_type) && anyelement_type != subtype)
544                                 return false;
545                         anyelement_type = subtype;
546                 }
547         }
548
549         if (have_anyarray_result && !OidIsValid(anyarray_type))
550                 anyarray_type = resolve_generic_type(ANYARRAYOID,
551                                                                                          anyelement_type,
552                                                                                          ANYELEMENTOID);
553
554         /*
555          * We can't deduce a range type from other polymorphic inputs, because
556          * there may be multiple range types for the same subtype.
557          */
558         if (have_anyrange_result && !OidIsValid(anyrange_type))
559                 return false;
560
561         /* Enforce ANYNONARRAY if needed */
562         if (have_anynonarray && type_is_array(anyelement_type))
563                 return false;
564
565         /* Enforce ANYENUM if needed */
566         if (have_anyenum && !type_is_enum(anyelement_type))
567                 return false;
568
569         /*
570          * Identify the collation to use for polymorphic OUT parameters. (It'll
571          * necessarily be the same for both anyelement and anyarray.)  Note that
572          * range types are not collatable, so any possible internal collation of a
573          * range type is not considered here.
574          */
575         if (OidIsValid(anyelement_type))
576                 anycollation = get_typcollation(anyelement_type);
577         else if (OidIsValid(anyarray_type))
578                 anycollation = get_typcollation(anyarray_type);
579
580         if (OidIsValid(anycollation))
581         {
582                 /*
583                  * The types are collatable, so consider whether to use a nondefault
584                  * collation.  We do so if we can identify the input collation used
585                  * for the function.
586                  */
587                 Oid                     inputcollation = exprInputCollation(call_expr);
588
589                 if (OidIsValid(inputcollation))
590                         anycollation = inputcollation;
591         }
592
593         /* And finally replace the tuple column types as needed */
594         for (i = 0; i < natts; i++)
595         {
596                 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
597
598                 switch (att->atttypid)
599                 {
600                         case ANYELEMENTOID:
601                         case ANYNONARRAYOID:
602                         case ANYENUMOID:
603                                 TupleDescInitEntry(tupdesc, i + 1,
604                                                                    NameStr(att->attname),
605                                                                    anyelement_type,
606                                                                    -1,
607                                                                    0);
608                                 TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
609                                 break;
610                         case ANYARRAYOID:
611                                 TupleDescInitEntry(tupdesc, i + 1,
612                                                                    NameStr(att->attname),
613                                                                    anyarray_type,
614                                                                    -1,
615                                                                    0);
616                                 TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
617                                 break;
618                         case ANYRANGEOID:
619                                 TupleDescInitEntry(tupdesc, i + 1,
620                                                                    NameStr(att->attname),
621                                                                    anyrange_type,
622                                                                    -1,
623                                                                    0);
624                                 /* no collation should be attached to a range type */
625                                 break;
626                         default:
627                                 break;
628                 }
629         }
630
631         return true;
632 }
633
634 /*
635  * Given the declared argument types and modes for a function, replace any
636  * polymorphic types (ANYELEMENT etc) with correct data types deduced from the
637  * input arguments.  Returns true if able to deduce all types, false if not.
638  * This is the same logic as resolve_polymorphic_tupdesc, but with a different
639  * argument representation.
640  *
641  * argmodes may be NULL, in which case all arguments are assumed to be IN mode.
642  */
643 bool
644 resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
645                                                          Node *call_expr)
646 {
647         bool            have_anyelement_result = false;
648         bool            have_anyarray_result = false;
649         bool            have_anyrange_result = false;
650         Oid                     anyelement_type = InvalidOid;
651         Oid                     anyarray_type = InvalidOid;
652         Oid                     anyrange_type = InvalidOid;
653         int                     inargno;
654         int                     i;
655
656         /* First pass: resolve polymorphic inputs, check for outputs */
657         inargno = 0;
658         for (i = 0; i < numargs; i++)
659         {
660                 char            argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
661
662                 switch (argtypes[i])
663                 {
664                         case ANYELEMENTOID:
665                         case ANYNONARRAYOID:
666                         case ANYENUMOID:
667                                 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
668                                         have_anyelement_result = true;
669                                 else
670                                 {
671                                         if (!OidIsValid(anyelement_type))
672                                         {
673                                                 anyelement_type = get_call_expr_argtype(call_expr,
674                                                                                                                                 inargno);
675                                                 if (!OidIsValid(anyelement_type))
676                                                         return false;
677                                         }
678                                         argtypes[i] = anyelement_type;
679                                 }
680                                 break;
681                         case ANYARRAYOID:
682                                 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
683                                         have_anyarray_result = true;
684                                 else
685                                 {
686                                         if (!OidIsValid(anyarray_type))
687                                         {
688                                                 anyarray_type = get_call_expr_argtype(call_expr,
689                                                                                                                           inargno);
690                                                 if (!OidIsValid(anyarray_type))
691                                                         return false;
692                                         }
693                                         argtypes[i] = anyarray_type;
694                                 }
695                                 break;
696                         case ANYRANGEOID:
697                                 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
698                                         have_anyrange_result = true;
699                                 else
700                                 {
701                                         if (!OidIsValid(anyrange_type))
702                                         {
703                                                 anyrange_type = get_call_expr_argtype(call_expr,
704                                                                                                                           inargno);
705                                                 if (!OidIsValid(anyrange_type))
706                                                         return false;
707                                         }
708                                         argtypes[i] = anyrange_type;
709                                 }
710                                 break;
711                         default:
712                                 break;
713                 }
714                 if (argmode != PROARGMODE_OUT && argmode != PROARGMODE_TABLE)
715                         inargno++;
716         }
717
718         /* Done? */
719         if (!have_anyelement_result && !have_anyarray_result &&
720                 !have_anyrange_result)
721                 return true;
722
723         /* If no input polymorphics, parser messed up */
724         if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type) &&
725                 !OidIsValid(anyrange_type))
726                 return false;
727
728         /* If needed, deduce one polymorphic type from others */
729         if (have_anyelement_result && !OidIsValid(anyelement_type))
730         {
731                 if (OidIsValid(anyarray_type))
732                         anyelement_type = resolve_generic_type(ANYELEMENTOID,
733                                                                                                    anyarray_type,
734                                                                                                    ANYARRAYOID);
735                 if (OidIsValid(anyrange_type))
736                 {
737                         Oid                     subtype = resolve_generic_type(ANYELEMENTOID,
738                                                                                                            anyrange_type,
739                                                                                                            ANYRANGEOID);
740
741                         /* check for inconsistent array and range results */
742                         if (OidIsValid(anyelement_type) && anyelement_type != subtype)
743                                 return false;
744                         anyelement_type = subtype;
745                 }
746         }
747
748         if (have_anyarray_result && !OidIsValid(anyarray_type))
749                 anyarray_type = resolve_generic_type(ANYARRAYOID,
750                                                                                          anyelement_type,
751                                                                                          ANYELEMENTOID);
752
753         /*
754          * We can't deduce a range type from other polymorphic inputs, because
755          * there may be multiple range types for the same subtype.
756          */
757         if (have_anyrange_result && !OidIsValid(anyrange_type))
758                 return false;
759
760         /* XXX do we need to enforce ANYNONARRAY or ANYENUM here?  I think not */
761
762         /* And finally replace the output column types as needed */
763         for (i = 0; i < numargs; i++)
764         {
765                 switch (argtypes[i])
766                 {
767                         case ANYELEMENTOID:
768                         case ANYNONARRAYOID:
769                         case ANYENUMOID:
770                                 argtypes[i] = anyelement_type;
771                                 break;
772                         case ANYARRAYOID:
773                                 argtypes[i] = anyarray_type;
774                                 break;
775                         case ANYRANGEOID:
776                                 argtypes[i] = anyrange_type;
777                                 break;
778                         default:
779                                 break;
780                 }
781         }
782
783         return true;
784 }
785
786 /*
787  * get_type_func_class
788  *              Given the type OID, obtain its TYPEFUNC classification.
789  *              Also, if it's a domain, return the base type OID.
790  *
791  * This is intended to centralize a bunch of formerly ad-hoc code for
792  * classifying types.  The categories used here are useful for deciding
793  * how to handle functions returning the datatype.
794  */
795 static TypeFuncClass
796 get_type_func_class(Oid typid, Oid *base_typeid)
797 {
798         *base_typeid = typid;
799
800         switch (get_typtype(typid))
801         {
802                 case TYPTYPE_COMPOSITE:
803                         return TYPEFUNC_COMPOSITE;
804                 case TYPTYPE_BASE:
805                 case TYPTYPE_ENUM:
806                 case TYPTYPE_RANGE:
807                         return TYPEFUNC_SCALAR;
808                 case TYPTYPE_DOMAIN:
809                         *base_typeid = typid = getBaseType(typid);
810                         if (get_typtype(typid) == TYPTYPE_COMPOSITE)
811                                 return TYPEFUNC_COMPOSITE_DOMAIN;
812                         else                            /* domain base type can't be a pseudotype */
813                                 return TYPEFUNC_SCALAR;
814                 case TYPTYPE_PSEUDO:
815                         if (typid == RECORDOID)
816                                 return TYPEFUNC_RECORD;
817
818                         /*
819                          * We treat VOID and CSTRING as legitimate scalar datatypes,
820                          * mostly for the convenience of the JDBC driver (which wants to
821                          * be able to do "SELECT * FROM foo()" for all legitimately
822                          * user-callable functions).
823                          */
824                         if (typid == VOIDOID || typid == CSTRINGOID)
825                                 return TYPEFUNC_SCALAR;
826                         return TYPEFUNC_OTHER;
827         }
828         /* shouldn't get here, probably */
829         return TYPEFUNC_OTHER;
830 }
831
832
833 /*
834  * get_func_arg_info
835  *
836  * Fetch info about the argument types, names, and IN/OUT modes from the
837  * pg_proc tuple.  Return value is the total number of arguments.
838  * Other results are palloc'd.  *p_argtypes is always filled in, but
839  * *p_argnames and *p_argmodes will be set NULL in the default cases
840  * (no names, and all IN arguments, respectively).
841  *
842  * Note that this function simply fetches what is in the pg_proc tuple;
843  * it doesn't do any interpretation of polymorphic types.
844  */
845 int
846 get_func_arg_info(HeapTuple procTup,
847                                   Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
848 {
849         Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
850         Datum           proallargtypes;
851         Datum           proargmodes;
852         Datum           proargnames;
853         bool            isNull;
854         ArrayType  *arr;
855         int                     numargs;
856         Datum      *elems;
857         int                     nelems;
858         int                     i;
859
860         /* First discover the total number of parameters and get their types */
861         proallargtypes = SysCacheGetAttr(PROCOID, procTup,
862                                                                          Anum_pg_proc_proallargtypes,
863                                                                          &isNull);
864         if (!isNull)
865         {
866                 /*
867                  * We expect the arrays to be 1-D arrays of the right types; verify
868                  * that.  For the OID and char arrays, we don't need to use
869                  * deconstruct_array() since the array data is just going to look like
870                  * a C array of values.
871                  */
872                 arr = DatumGetArrayTypeP(proallargtypes);       /* ensure not toasted */
873                 numargs = ARR_DIMS(arr)[0];
874                 if (ARR_NDIM(arr) != 1 ||
875                         numargs < 0 ||
876                         ARR_HASNULL(arr) ||
877                         ARR_ELEMTYPE(arr) != OIDOID)
878                         elog(ERROR, "proallargtypes is not a 1-D Oid array");
879                 Assert(numargs >= procStruct->pronargs);
880                 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
881                 memcpy(*p_argtypes, ARR_DATA_PTR(arr),
882                            numargs * sizeof(Oid));
883         }
884         else
885         {
886                 /* If no proallargtypes, use proargtypes */
887                 numargs = procStruct->proargtypes.dim1;
888                 Assert(numargs == procStruct->pronargs);
889                 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
890                 memcpy(*p_argtypes, procStruct->proargtypes.values,
891                            numargs * sizeof(Oid));
892         }
893
894         /* Get argument names, if available */
895         proargnames = SysCacheGetAttr(PROCOID, procTup,
896                                                                   Anum_pg_proc_proargnames,
897                                                                   &isNull);
898         if (isNull)
899                 *p_argnames = NULL;
900         else
901         {
902                 deconstruct_array(DatumGetArrayTypeP(proargnames),
903                                                   TEXTOID, -1, false, 'i',
904                                                   &elems, NULL, &nelems);
905                 if (nelems != numargs)  /* should not happen */
906                         elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
907                 *p_argnames = (char **) palloc(sizeof(char *) * numargs);
908                 for (i = 0; i < numargs; i++)
909                         (*p_argnames)[i] = TextDatumGetCString(elems[i]);
910         }
911
912         /* Get argument modes, if available */
913         proargmodes = SysCacheGetAttr(PROCOID, procTup,
914                                                                   Anum_pg_proc_proargmodes,
915                                                                   &isNull);
916         if (isNull)
917                 *p_argmodes = NULL;
918         else
919         {
920                 arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
921                 if (ARR_NDIM(arr) != 1 ||
922                         ARR_DIMS(arr)[0] != numargs ||
923                         ARR_HASNULL(arr) ||
924                         ARR_ELEMTYPE(arr) != CHAROID)
925                         elog(ERROR, "proargmodes is not a 1-D char array");
926                 *p_argmodes = (char *) palloc(numargs * sizeof(char));
927                 memcpy(*p_argmodes, ARR_DATA_PTR(arr),
928                            numargs * sizeof(char));
929         }
930
931         return numargs;
932 }
933
934 /*
935  * get_func_trftypes
936  *
937  * Returns the number of transformed types used by function.
938  */
939 int
940 get_func_trftypes(HeapTuple procTup,
941                                   Oid **p_trftypes)
942 {
943         Datum           protrftypes;
944         ArrayType  *arr;
945         int                     nelems;
946         bool            isNull;
947
948         protrftypes = SysCacheGetAttr(PROCOID, procTup,
949                                                                   Anum_pg_proc_protrftypes,
950                                                                   &isNull);
951         if (!isNull)
952         {
953                 /*
954                  * We expect the arrays to be 1-D arrays of the right types; verify
955                  * that.  For the OID and char arrays, we don't need to use
956                  * deconstruct_array() since the array data is just going to look like
957                  * a C array of values.
958                  */
959                 arr = DatumGetArrayTypeP(protrftypes);  /* ensure not toasted */
960                 nelems = ARR_DIMS(arr)[0];
961                 if (ARR_NDIM(arr) != 1 ||
962                         nelems < 0 ||
963                         ARR_HASNULL(arr) ||
964                         ARR_ELEMTYPE(arr) != OIDOID)
965                         elog(ERROR, "protrftypes is not a 1-D Oid array");
966                 Assert(nelems >= ((Form_pg_proc) GETSTRUCT(procTup))->pronargs);
967                 *p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
968                 memcpy(*p_trftypes, ARR_DATA_PTR(arr),
969                            nelems * sizeof(Oid));
970
971                 return nelems;
972         }
973         else
974                 return 0;
975 }
976
977 /*
978  * get_func_input_arg_names
979  *
980  * Extract the names of input arguments only, given a function's
981  * proargnames and proargmodes entries in Datum form.
982  *
983  * Returns the number of input arguments, which is the length of the
984  * palloc'd array returned to *arg_names.  Entries for unnamed args
985  * are set to NULL.  You don't get anything if proargnames is NULL.
986  */
987 int
988 get_func_input_arg_names(Datum proargnames, Datum proargmodes,
989                                                  char ***arg_names)
990 {
991         ArrayType  *arr;
992         int                     numargs;
993         Datum      *argnames;
994         char       *argmodes;
995         char      **inargnames;
996         int                     numinargs;
997         int                     i;
998
999         /* Do nothing if null proargnames */
1000         if (proargnames == PointerGetDatum(NULL))
1001         {
1002                 *arg_names = NULL;
1003                 return 0;
1004         }
1005
1006         /*
1007          * We expect the arrays to be 1-D arrays of the right types; verify that.
1008          * For proargmodes, we don't need to use deconstruct_array() since the
1009          * array data is just going to look like a C array of values.
1010          */
1011         arr = DatumGetArrayTypeP(proargnames);  /* ensure not toasted */
1012         if (ARR_NDIM(arr) != 1 ||
1013                 ARR_HASNULL(arr) ||
1014                 ARR_ELEMTYPE(arr) != TEXTOID)
1015                 elog(ERROR, "proargnames is not a 1-D text array");
1016         deconstruct_array(arr, TEXTOID, -1, false, 'i',
1017                                           &argnames, NULL, &numargs);
1018         if (proargmodes != PointerGetDatum(NULL))
1019         {
1020                 arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
1021                 if (ARR_NDIM(arr) != 1 ||
1022                         ARR_DIMS(arr)[0] != numargs ||
1023                         ARR_HASNULL(arr) ||
1024                         ARR_ELEMTYPE(arr) != CHAROID)
1025                         elog(ERROR, "proargmodes is not a 1-D char array");
1026                 argmodes = (char *) ARR_DATA_PTR(arr);
1027         }
1028         else
1029                 argmodes = NULL;
1030
1031         /* zero elements probably shouldn't happen, but handle it gracefully */
1032         if (numargs <= 0)
1033         {
1034                 *arg_names = NULL;
1035                 return 0;
1036         }
1037
1038         /* extract input-argument names */
1039         inargnames = (char **) palloc(numargs * sizeof(char *));
1040         numinargs = 0;
1041         for (i = 0; i < numargs; i++)
1042         {
1043                 if (argmodes == NULL ||
1044                         argmodes[i] == PROARGMODE_IN ||
1045                         argmodes[i] == PROARGMODE_INOUT ||
1046                         argmodes[i] == PROARGMODE_VARIADIC)
1047                 {
1048                         char       *pname = TextDatumGetCString(argnames[i]);
1049
1050                         if (pname[0] != '\0')
1051                                 inargnames[numinargs] = pname;
1052                         else
1053                                 inargnames[numinargs] = NULL;
1054                         numinargs++;
1055                 }
1056         }
1057
1058         *arg_names = inargnames;
1059         return numinargs;
1060 }
1061
1062
1063 /*
1064  * get_func_result_name
1065  *
1066  * If the function has exactly one output parameter, and that parameter
1067  * is named, return the name (as a palloc'd string).  Else return NULL.
1068  *
1069  * This is used to determine the default output column name for functions
1070  * returning scalar types.
1071  */
1072 char *
1073 get_func_result_name(Oid functionId)
1074 {
1075         char       *result;
1076         HeapTuple       procTuple;
1077         Datum           proargmodes;
1078         Datum           proargnames;
1079         bool            isnull;
1080         ArrayType  *arr;
1081         int                     numargs;
1082         char       *argmodes;
1083         Datum      *argnames;
1084         int                     numoutargs;
1085         int                     nargnames;
1086         int                     i;
1087
1088         /* First fetch the function's pg_proc row */
1089         procTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
1090         if (!HeapTupleIsValid(procTuple))
1091                 elog(ERROR, "cache lookup failed for function %u", functionId);
1092
1093         /* If there are no named OUT parameters, return NULL */
1094         if (heap_attisnull(procTuple, Anum_pg_proc_proargmodes, NULL) ||
1095                 heap_attisnull(procTuple, Anum_pg_proc_proargnames, NULL))
1096                 result = NULL;
1097         else
1098         {
1099                 /* Get the data out of the tuple */
1100                 proargmodes = SysCacheGetAttr(PROCOID, procTuple,
1101                                                                           Anum_pg_proc_proargmodes,
1102                                                                           &isnull);
1103                 Assert(!isnull);
1104                 proargnames = SysCacheGetAttr(PROCOID, procTuple,
1105                                                                           Anum_pg_proc_proargnames,
1106                                                                           &isnull);
1107                 Assert(!isnull);
1108
1109                 /*
1110                  * We expect the arrays to be 1-D arrays of the right types; verify
1111                  * that.  For the char array, we don't need to use deconstruct_array()
1112                  * since the array data is just going to look like a C array of
1113                  * values.
1114                  */
1115                 arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
1116                 numargs = ARR_DIMS(arr)[0];
1117                 if (ARR_NDIM(arr) != 1 ||
1118                         numargs < 0 ||
1119                         ARR_HASNULL(arr) ||
1120                         ARR_ELEMTYPE(arr) != CHAROID)
1121                         elog(ERROR, "proargmodes is not a 1-D char array");
1122                 argmodes = (char *) ARR_DATA_PTR(arr);
1123                 arr = DatumGetArrayTypeP(proargnames);  /* ensure not toasted */
1124                 if (ARR_NDIM(arr) != 1 ||
1125                         ARR_DIMS(arr)[0] != numargs ||
1126                         ARR_HASNULL(arr) ||
1127                         ARR_ELEMTYPE(arr) != TEXTOID)
1128                         elog(ERROR, "proargnames is not a 1-D text array");
1129                 deconstruct_array(arr, TEXTOID, -1, false, 'i',
1130                                                   &argnames, NULL, &nargnames);
1131                 Assert(nargnames == numargs);
1132
1133                 /* scan for output argument(s) */
1134                 result = NULL;
1135                 numoutargs = 0;
1136                 for (i = 0; i < numargs; i++)
1137                 {
1138                         if (argmodes[i] == PROARGMODE_IN ||
1139                                 argmodes[i] == PROARGMODE_VARIADIC)
1140                                 continue;
1141                         Assert(argmodes[i] == PROARGMODE_OUT ||
1142                                    argmodes[i] == PROARGMODE_INOUT ||
1143                                    argmodes[i] == PROARGMODE_TABLE);
1144                         if (++numoutargs > 1)
1145                         {
1146                                 /* multiple out args, so forget it */
1147                                 result = NULL;
1148                                 break;
1149                         }
1150                         result = TextDatumGetCString(argnames[i]);
1151                         if (result == NULL || result[0] == '\0')
1152                         {
1153                                 /* Parameter is not named, so forget it */
1154                                 result = NULL;
1155                                 break;
1156                         }
1157                 }
1158         }
1159
1160         ReleaseSysCache(procTuple);
1161
1162         return result;
1163 }
1164
1165
1166 /*
1167  * build_function_result_tupdesc_t
1168  *
1169  * Given a pg_proc row for a function, return a tuple descriptor for the
1170  * result rowtype, or NULL if the function does not have OUT parameters.
1171  *
1172  * Note that this does not handle resolution of polymorphic types;
1173  * that is deliberate.
1174  */
1175 TupleDesc
1176 build_function_result_tupdesc_t(HeapTuple procTuple)
1177 {
1178         Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(procTuple);
1179         Datum           proallargtypes;
1180         Datum           proargmodes;
1181         Datum           proargnames;
1182         bool            isnull;
1183
1184         /* Return NULL if the function isn't declared to return RECORD */
1185         if (procform->prorettype != RECORDOID)
1186                 return NULL;
1187
1188         /* If there are no OUT parameters, return NULL */
1189         if (heap_attisnull(procTuple, Anum_pg_proc_proallargtypes, NULL) ||
1190                 heap_attisnull(procTuple, Anum_pg_proc_proargmodes, NULL))
1191                 return NULL;
1192
1193         /* Get the data out of the tuple */
1194         proallargtypes = SysCacheGetAttr(PROCOID, procTuple,
1195                                                                          Anum_pg_proc_proallargtypes,
1196                                                                          &isnull);
1197         Assert(!isnull);
1198         proargmodes = SysCacheGetAttr(PROCOID, procTuple,
1199                                                                   Anum_pg_proc_proargmodes,
1200                                                                   &isnull);
1201         Assert(!isnull);
1202         proargnames = SysCacheGetAttr(PROCOID, procTuple,
1203                                                                   Anum_pg_proc_proargnames,
1204                                                                   &isnull);
1205         if (isnull)
1206                 proargnames = PointerGetDatum(NULL);    /* just to be sure */
1207
1208         return build_function_result_tupdesc_d(procform->prokind,
1209                                                                                    proallargtypes,
1210                                                                                    proargmodes,
1211                                                                                    proargnames);
1212 }
1213
1214 /*
1215  * build_function_result_tupdesc_d
1216  *
1217  * Build a RECORD function's tupledesc from the pg_proc proallargtypes,
1218  * proargmodes, and proargnames arrays.  This is split out for the
1219  * convenience of ProcedureCreate, which needs to be able to compute the
1220  * tupledesc before actually creating the function.
1221  *
1222  * For functions (but not for procedures), returns NULL if there are not at
1223  * least two OUT or INOUT arguments.
1224  */
1225 TupleDesc
1226 build_function_result_tupdesc_d(char prokind,
1227                                                                 Datum proallargtypes,
1228                                                                 Datum proargmodes,
1229                                                                 Datum proargnames)
1230 {
1231         TupleDesc       desc;
1232         ArrayType  *arr;
1233         int                     numargs;
1234         Oid                *argtypes;
1235         char       *argmodes;
1236         Datum      *argnames = NULL;
1237         Oid                *outargtypes;
1238         char      **outargnames;
1239         int                     numoutargs;
1240         int                     nargnames;
1241         int                     i;
1242
1243         /* Can't have output args if columns are null */
1244         if (proallargtypes == PointerGetDatum(NULL) ||
1245                 proargmodes == PointerGetDatum(NULL))
1246                 return NULL;
1247
1248         /*
1249          * We expect the arrays to be 1-D arrays of the right types; verify that.
1250          * For the OID and char arrays, we don't need to use deconstruct_array()
1251          * since the array data is just going to look like a C array of values.
1252          */
1253         arr = DatumGetArrayTypeP(proallargtypes);       /* ensure not toasted */
1254         numargs = ARR_DIMS(arr)[0];
1255         if (ARR_NDIM(arr) != 1 ||
1256                 numargs < 0 ||
1257                 ARR_HASNULL(arr) ||
1258                 ARR_ELEMTYPE(arr) != OIDOID)
1259                 elog(ERROR, "proallargtypes is not a 1-D Oid array");
1260         argtypes = (Oid *) ARR_DATA_PTR(arr);
1261         arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
1262         if (ARR_NDIM(arr) != 1 ||
1263                 ARR_DIMS(arr)[0] != numargs ||
1264                 ARR_HASNULL(arr) ||
1265                 ARR_ELEMTYPE(arr) != CHAROID)
1266                 elog(ERROR, "proargmodes is not a 1-D char array");
1267         argmodes = (char *) ARR_DATA_PTR(arr);
1268         if (proargnames != PointerGetDatum(NULL))
1269         {
1270                 arr = DatumGetArrayTypeP(proargnames);  /* ensure not toasted */
1271                 if (ARR_NDIM(arr) != 1 ||
1272                         ARR_DIMS(arr)[0] != numargs ||
1273                         ARR_HASNULL(arr) ||
1274                         ARR_ELEMTYPE(arr) != TEXTOID)
1275                         elog(ERROR, "proargnames is not a 1-D text array");
1276                 deconstruct_array(arr, TEXTOID, -1, false, 'i',
1277                                                   &argnames, NULL, &nargnames);
1278                 Assert(nargnames == numargs);
1279         }
1280
1281         /* zero elements probably shouldn't happen, but handle it gracefully */
1282         if (numargs <= 0)
1283                 return NULL;
1284
1285         /* extract output-argument types and names */
1286         outargtypes = (Oid *) palloc(numargs * sizeof(Oid));
1287         outargnames = (char **) palloc(numargs * sizeof(char *));
1288         numoutargs = 0;
1289         for (i = 0; i < numargs; i++)
1290         {
1291                 char       *pname;
1292
1293                 if (argmodes[i] == PROARGMODE_IN ||
1294                         argmodes[i] == PROARGMODE_VARIADIC)
1295                         continue;
1296                 Assert(argmodes[i] == PROARGMODE_OUT ||
1297                            argmodes[i] == PROARGMODE_INOUT ||
1298                            argmodes[i] == PROARGMODE_TABLE);
1299                 outargtypes[numoutargs] = argtypes[i];
1300                 if (argnames)
1301                         pname = TextDatumGetCString(argnames[i]);
1302                 else
1303                         pname = NULL;
1304                 if (pname == NULL || pname[0] == '\0')
1305                 {
1306                         /* Parameter is not named, so gin up a column name */
1307                         pname = psprintf("column%d", numoutargs + 1);
1308                 }
1309                 outargnames[numoutargs] = pname;
1310                 numoutargs++;
1311         }
1312
1313         /*
1314          * If there is no output argument, or only one, the function does not
1315          * return tuples.
1316          */
1317         if (numoutargs < 2 && prokind != PROKIND_PROCEDURE)
1318                 return NULL;
1319
1320         desc = CreateTemplateTupleDesc(numoutargs, false);
1321         for (i = 0; i < numoutargs; i++)
1322         {
1323                 TupleDescInitEntry(desc, i + 1,
1324                                                    outargnames[i],
1325                                                    outargtypes[i],
1326                                                    -1,
1327                                                    0);
1328         }
1329
1330         return desc;
1331 }
1332
1333
1334 /*
1335  * RelationNameGetTupleDesc
1336  *
1337  * Given a (possibly qualified) relation name, build a TupleDesc.
1338  *
1339  * Note: while this works as advertised, it's seldom the best way to
1340  * build a tupdesc for a function's result type.  It's kept around
1341  * only for backwards compatibility with existing user-written code.
1342  */
1343 TupleDesc
1344 RelationNameGetTupleDesc(const char *relname)
1345 {
1346         RangeVar   *relvar;
1347         Relation        rel;
1348         TupleDesc       tupdesc;
1349         List       *relname_list;
1350
1351         /* Open relation and copy the tuple description */
1352         relname_list = stringToQualifiedNameList(relname);
1353         relvar = makeRangeVarFromNameList(relname_list);
1354         rel = relation_openrv(relvar, AccessShareLock);
1355         tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
1356         relation_close(rel, AccessShareLock);
1357
1358         return tupdesc;
1359 }
1360
1361 /*
1362  * TypeGetTupleDesc
1363  *
1364  * Given a type Oid, build a TupleDesc.  (In most cases you should be
1365  * using get_call_result_type or one of its siblings instead of this
1366  * routine, so that you can handle OUT parameters, RECORD result type,
1367  * and polymorphic results.)
1368  *
1369  * If the type is composite, *and* a colaliases List is provided, *and*
1370  * the List is of natts length, use the aliases instead of the relation
1371  * attnames.  (NB: this usage is deprecated since it may result in
1372  * creation of unnecessary transient record types.)
1373  *
1374  * If the type is a base type, a single item alias List is required.
1375  */
1376 TupleDesc
1377 TypeGetTupleDesc(Oid typeoid, List *colaliases)
1378 {
1379         Oid                     base_typeoid;
1380         TypeFuncClass functypclass = get_type_func_class(typeoid, &base_typeoid);
1381         TupleDesc       tupdesc = NULL;
1382
1383         /*
1384          * Build a suitable tupledesc representing the output rows.  We
1385          * intentionally do not support TYPEFUNC_COMPOSITE_DOMAIN here, as it's
1386          * unlikely that legacy callers of this obsolete function would be
1387          * prepared to apply domain constraints.
1388          */
1389         if (functypclass == TYPEFUNC_COMPOSITE)
1390         {
1391                 /* Composite data type, e.g. a table's row type */
1392                 tupdesc = lookup_rowtype_tupdesc_copy(base_typeoid, -1);
1393
1394                 if (colaliases != NIL)
1395                 {
1396                         int                     natts = tupdesc->natts;
1397                         int                     varattno;
1398
1399                         /* does the list length match the number of attributes? */
1400                         if (list_length(colaliases) != natts)
1401                                 ereport(ERROR,
1402                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
1403                                                  errmsg("number of aliases does not match number of columns")));
1404
1405                         /* OK, use the aliases instead */
1406                         for (varattno = 0; varattno < natts; varattno++)
1407                         {
1408                                 char       *label = strVal(list_nth(colaliases, varattno));
1409                                 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
1410
1411                                 if (label != NULL)
1412                                         namestrcpy(&(attr->attname), label);
1413                         }
1414
1415                         /* The tuple type is now an anonymous record type */
1416                         tupdesc->tdtypeid = RECORDOID;
1417                         tupdesc->tdtypmod = -1;
1418                 }
1419         }
1420         else if (functypclass == TYPEFUNC_SCALAR)
1421         {
1422                 /* Base data type, i.e. scalar */
1423                 char       *attname;
1424
1425                 /* the alias list is required for base types */
1426                 if (colaliases == NIL)
1427                         ereport(ERROR,
1428                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
1429                                          errmsg("no column alias was provided")));
1430
1431                 /* the alias list length must be 1 */
1432                 if (list_length(colaliases) != 1)
1433                         ereport(ERROR,
1434                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
1435                                          errmsg("number of aliases does not match number of columns")));
1436
1437                 /* OK, get the column alias */
1438                 attname = strVal(linitial(colaliases));
1439
1440                 tupdesc = CreateTemplateTupleDesc(1, false);
1441                 TupleDescInitEntry(tupdesc,
1442                                                    (AttrNumber) 1,
1443                                                    attname,
1444                                                    typeoid,
1445                                                    -1,
1446                                                    0);
1447         }
1448         else if (functypclass == TYPEFUNC_RECORD)
1449         {
1450                 /* XXX can't support this because typmod wasn't passed in ... */
1451                 ereport(ERROR,
1452                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
1453                                  errmsg("could not determine row description for function returning record")));
1454         }
1455         else
1456         {
1457                 /* crummy error message, but parser should have caught this */
1458                 elog(ERROR, "function in FROM has unsupported return type");
1459         }
1460
1461         return tupdesc;
1462 }
1463
1464 /*
1465  * extract_variadic_args
1466  *
1467  * Extract a set of argument values, types and NULL markers for a given
1468  * input function which makes use of a VARIADIC input whose argument list
1469  * depends on the caller context. When doing a VARIADIC call, the caller
1470  * has provided one argument made of an array of values, so deconstruct the
1471  * array data before using it for the next processing. If no VARIADIC call
1472  * is used, just fill in the status data based on all the arguments given
1473  * by the caller.
1474  *
1475  * This function returns the number of arguments generated, or -1 in the
1476  * case of "VARIADIC NULL".
1477  */
1478 int
1479 extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
1480                                           bool convert_unknown, Datum **args, Oid **types,
1481                                           bool **nulls)
1482 {
1483         bool            variadic = get_fn_expr_variadic(fcinfo->flinfo);
1484         Datum      *args_res;
1485         bool       *nulls_res;
1486         Oid                *types_res;
1487         int                     nargs,
1488                                 i;
1489
1490         *args = NULL;
1491         *types = NULL;
1492         *nulls = NULL;
1493
1494         if (variadic)
1495         {
1496                 ArrayType  *array_in;
1497                 Oid                     element_type;
1498                 bool            typbyval;
1499                 char            typalign;
1500                 int16           typlen;
1501
1502                 Assert(PG_NARGS() == variadic_start + 1);
1503
1504                 if (PG_ARGISNULL(variadic_start))
1505                         return -1;
1506
1507                 array_in = PG_GETARG_ARRAYTYPE_P(variadic_start);
1508                 element_type = ARR_ELEMTYPE(array_in);
1509
1510                 get_typlenbyvalalign(element_type,
1511                                                          &typlen, &typbyval, &typalign);
1512                 deconstruct_array(array_in, element_type, typlen, typbyval,
1513                                                   typalign, &args_res, &nulls_res,
1514                                                   &nargs);
1515
1516                 /* All the elements of the array have the same type */
1517                 types_res = (Oid *) palloc0(nargs * sizeof(Oid));
1518                 for (i = 0; i < nargs; i++)
1519                         types_res[i] = element_type;
1520         }
1521         else
1522         {
1523                 nargs = PG_NARGS() - variadic_start;
1524                 Assert(nargs > 0);
1525                 nulls_res = (bool *) palloc0(nargs * sizeof(bool));
1526                 args_res = (Datum *) palloc0(nargs * sizeof(Datum));
1527                 types_res = (Oid *) palloc0(nargs * sizeof(Oid));
1528
1529                 for (i = 0; i < nargs; i++)
1530                 {
1531                         nulls_res[i] = PG_ARGISNULL(i + variadic_start);
1532                         types_res[i] = get_fn_expr_argtype(fcinfo->flinfo,
1533                                                                                            i + variadic_start);
1534
1535                         /*
1536                          * Turn a constant (more or less literal) value that's of unknown
1537                          * type into text if required. Unknowns come in as a cstring
1538                          * pointer. Note: for functions declared as taking type "any", the
1539                          * parser will not do any type conversion on unknown-type literals
1540                          * (that is, undecorated strings or NULLs).
1541                          */
1542                         if (convert_unknown &&
1543                                 types_res[i] == UNKNOWNOID &&
1544                                 get_fn_expr_arg_stable(fcinfo->flinfo, i + variadic_start))
1545                         {
1546                                 types_res[i] = TEXTOID;
1547
1548                                 if (PG_ARGISNULL(i + variadic_start))
1549                                         args_res[i] = (Datum) 0;
1550                                 else
1551                                         args_res[i] =
1552                                                 CStringGetTextDatum(PG_GETARG_POINTER(i + variadic_start));
1553                         }
1554                         else
1555                         {
1556                                 /* no conversion needed, just take the datum as given */
1557                                 args_res[i] = PG_GETARG_DATUM(i + variadic_start);
1558                         }
1559
1560                         if (!OidIsValid(types_res[i]) ||
1561                                 (convert_unknown && types_res[i] == UNKNOWNOID))
1562                                 ereport(ERROR,
1563                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1564                                                  errmsg("could not determine data type for argument %d",
1565                                                                 i + 1)));
1566                 }
1567         }
1568
1569         /* Fill in results */
1570         *args = args_res;
1571         *nulls = nulls_res;
1572         *types = types_res;
1573
1574         return nargs;
1575 }