Age Owner TLA Line data Source code
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-2023, 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 "access/relation.h"
18 : #include "catalog/namespace.h"
19 : #include "catalog/pg_proc.h"
20 : #include "catalog/pg_type.h"
21 : #include "funcapi.h"
22 : #include "miscadmin.h"
23 : #include "nodes/nodeFuncs.h"
24 : #include "utils/array.h"
25 : #include "utils/builtins.h"
26 : #include "utils/lsyscache.h"
27 : #include "utils/memutils.h"
28 : #include "utils/regproc.h"
29 : #include "utils/rel.h"
30 : #include "utils/syscache.h"
31 : #include "utils/tuplestore.h"
32 : #include "utils/typcache.h"
33 :
34 :
35 : typedef struct polymorphic_actuals
36 : {
37 : Oid anyelement_type; /* anyelement mapping, if known */
38 : Oid anyarray_type; /* anyarray mapping, if known */
39 : Oid anyrange_type; /* anyrange mapping, if known */
40 : Oid anymultirange_type; /* anymultirange mapping, if known */
41 : } polymorphic_actuals;
42 :
43 : static void shutdown_MultiFuncCall(Datum arg);
44 : static TypeFuncClass internal_get_result_type(Oid funcid,
45 : Node *call_expr,
46 : ReturnSetInfo *rsinfo,
47 : Oid *resultTypeId,
48 : TupleDesc *resultTupleDesc);
49 : static void resolve_anyelement_from_others(polymorphic_actuals *actuals);
50 : static void resolve_anyarray_from_others(polymorphic_actuals *actuals);
51 : static void resolve_anyrange_from_others(polymorphic_actuals *actuals);
52 : static void resolve_anymultirange_from_others(polymorphic_actuals *actuals);
53 : static bool resolve_polymorphic_tupdesc(TupleDesc tupdesc,
54 : oidvector *declared_args,
55 : Node *call_expr);
56 : static TypeFuncClass get_type_func_class(Oid typid, Oid *base_typeid);
57 :
58 :
59 : /*
60 : * InitMaterializedSRF
61 : *
62 : * Helper function to build the state of a set-returning function used
63 : * in the context of a single call with materialize mode. This code
64 : * includes sanity checks on ReturnSetInfo, creates the Tuplestore and
65 : * the TupleDesc used with the function and stores them into the
66 : * function's ReturnSetInfo.
398 michael 67 ECB : *
68 : * "flags" can be set to MAT_SRF_USE_EXPECTED_DESC, to use the tuple
69 : * descriptor coming from expectedDesc, which is the tuple descriptor
173 70 : * expected by the caller. MAT_SRF_BLESS can be set to complete the
71 : * information associated to the tuple descriptor, which is necessary
72 : * in some cases where the tuple descriptor comes from a transient
73 : * RECORD datatype.
74 : */
75 : void
173 michael 76 GIC 12102 : InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
398 michael 77 ECB : {
398 michael 78 EUB : bool random_access;
398 michael 79 GIC 12102 : ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
80 : Tuplestorestate *tupstore;
398 michael 81 ECB : MemoryContext old_context,
82 : per_query_ctx;
398 michael 83 EUB : TupleDesc stored_tupdesc;
84 :
85 : /* check to see if caller supports returning a tuplestore */
398 michael 86 GIC 12102 : if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
398 michael 87 UIC 0 : ereport(ERROR,
88 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
89 : errmsg("set-valued function called in context that cannot accept a set")));
398 michael 90 GIC 12102 : if (!(rsinfo->allowedModes & SFRM_Materialize) ||
173 michael 91 CBC 12102 : ((flags & MAT_SRF_USE_EXPECTED_DESC) != 0 && rsinfo->expectedDesc == NULL))
398 michael 92 LBC 0 : ereport(ERROR,
93 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
94 : errmsg("materialize mode required, but it is not allowed in this context")));
398 michael 95 ECB :
96 : /*
97 : * Store the tuplestore and the tuple descriptor in ReturnSetInfo. This
98 : * must be done in the per-query memory context.
99 : */
398 michael 100 GBC 12102 : per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
398 michael 101 GIC 12102 : old_context = MemoryContextSwitchTo(per_query_ctx);
102 :
103 : /* build a tuple descriptor for our result type */
173 michael 104 CBC 12102 : if ((flags & MAT_SRF_USE_EXPECTED_DESC) != 0)
398 105 963 : stored_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
106 : else
398 michael 107 ECB : {
398 michael 108 GIC 11139 : if (get_call_result_type(fcinfo, NULL, &stored_tupdesc) != TYPEFUNC_COMPOSITE)
398 michael 109 LBC 0 : elog(ERROR, "return type must be a row type");
398 michael 110 ECB : }
111 :
112 : /* If requested, bless the tuple descriptor */
173 michael 113 CBC 12102 : if ((flags & MAT_SRF_BLESS) != 0)
398 114 6333 : BlessTupleDesc(stored_tupdesc);
115 :
398 michael 116 GIC 12102 : random_access = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
117 :
118 12102 : tupstore = tuplestore_begin_heap(random_access, false, work_mem);
119 12102 : rsinfo->returnMode = SFRM_Materialize;
120 12102 : rsinfo->setResult = tupstore;
121 12102 : rsinfo->setDesc = stored_tupdesc;
122 12102 : MemoryContextSwitchTo(old_context);
123 12102 : }
398 michael 124 ECB :
125 :
126 : /*
127 : * init_MultiFuncCall
128 : * Create an empty FuncCallContext data structure
129 : * and do some other basic Multi-function call setup
130 : * and error checking
7598 bruce 131 : */
7598 bruce 132 EUB : FuncCallContext *
7598 bruce 133 GIC 81138 : init_MultiFuncCall(PG_FUNCTION_ARGS)
134 : {
135 : FuncCallContext *retval;
7598 bruce 136 ECB :
137 : /*
138 : * Bail if we're called in the wrong context
139 : */
7598 bruce 140 GIC 81138 : if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
7198 tgl 141 LBC 0 : ereport(ERROR,
142 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
143 : errmsg("set-valued function called in context that cannot accept a set")));
144 :
7598 bruce 145 GIC 81138 : if (fcinfo->flinfo->fn_extra == NULL)
146 : {
7598 bruce 147 ECB : /*
148 : * First call
149 : */
5050 bruce 150 GIC 81138 : ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
151 : MemoryContext multi_call_ctx;
152 :
153 : /*
154 : * Create a suitably long-lived context to hold cross-call data
5518 neilc 155 ECB : */
5518 neilc 156 GIC 81138 : multi_call_ctx = AllocSetContextCreate(fcinfo->flinfo->fn_mcxt,
157 : "SRF multi-call context",
158 : ALLOCSET_SMALL_SIZES);
159 :
160 : /*
7528 tgl 161 ECB : * Allocate suitably long-lived space and zero it
7598 bruce 162 : */
7528 tgl 163 : retval = (FuncCallContext *)
5518 neilc 164 CBC 81138 : MemoryContextAllocZero(multi_call_ctx,
6947 tgl 165 ECB : sizeof(FuncCallContext));
7598 bruce 166 :
167 : /*
168 : * initialize the elements
169 : */
7598 bruce 170 GIC 81138 : retval->call_cntr = 0;
7598 bruce 171 CBC 81138 : retval->max_calls = 0;
7570 bruce 172 GIC 81138 : retval->user_fctx = NULL;
7598 173 81138 : retval->attinmeta = NULL;
6947 tgl 174 81138 : retval->tuple_desc = NULL;
5518 neilc 175 81138 : retval->multi_call_memory_ctx = multi_call_ctx;
176 :
7598 bruce 177 ECB : /*
178 : * save the pointer for cross-call use
179 : */
7598 bruce 180 GIC 81138 : fcinfo->flinfo->fn_extra = retval;
181 :
182 : /*
183 : * Ensure we will get shut down cleanly if the exprcontext is not run
6385 bruce 184 EUB : * to completion.
185 : */
7051 mail 186 GIC 81138 : RegisterExprContextCallback(rsi->econtext,
187 : shutdown_MultiFuncCall,
188 81138 : PointerGetDatum(fcinfo->flinfo));
189 : }
7522 bruce 190 ECB : else
191 : {
192 : /* second and subsequent calls */
5911 bruce 193 UIC 0 : elog(ERROR, "init_MultiFuncCall cannot be called more than once");
194 :
195 : /* never reached, but keep compiler happy */
196 : retval = NULL;
197 : }
198 :
7598 bruce 199 CBC 81138 : return retval;
200 : }
7598 bruce 201 ECB :
202 : /*
7570 203 : * per_MultiFuncCall
204 : *
205 : * Do Multi-function per-call setup
206 : */
207 : FuncCallContext *
7570 bruce 208 GIC 8401397 : per_MultiFuncCall(PG_FUNCTION_ARGS)
209 : {
210 8401397 : FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
7570 bruce 211 ECB :
7570 bruce 212 GIC 8401397 : return retval;
7570 bruce 213 ECB : }
214 :
215 : /*
7598 216 : * end_MultiFuncCall
217 : * Clean up after init_MultiFuncCall
218 : */
219 : void
7598 bruce 220 GIC 80702 : end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
7598 bruce 221 ECB : {
6797 bruce 222 CBC 80702 : ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
223 :
224 : /* Deregister the shutdown callback */
7051 mail 225 GIC 80702 : UnregisterExprContextCallback(rsi->econtext,
226 : shutdown_MultiFuncCall,
227 80702 : PointerGetDatum(fcinfo->flinfo));
228 :
7051 mail 229 ECB : /* But use it to do the real work */
7051 mail 230 GIC 80702 : shutdown_MultiFuncCall(PointerGetDatum(fcinfo->flinfo));
7051 mail 231 CBC 80702 : }
7051 mail 232 ECB :
233 : /*
234 : * shutdown_MultiFuncCall
235 : * Shutdown function to clean up after init_MultiFuncCall
236 : */
237 : static void
7051 mail 238 GIC 80735 : shutdown_MultiFuncCall(Datum arg)
239 : {
6797 bruce 240 80735 : FmgrInfo *flinfo = (FmgrInfo *) DatumGetPointer(arg);
7051 mail 241 CBC 80735 : FuncCallContext *funcctx = (FuncCallContext *) flinfo->fn_extra;
7051 mail 242 ECB :
243 : /* unbind from flinfo */
7051 mail 244 GIC 80735 : flinfo->fn_extra = NULL;
245 :
246 : /*
247 : * Delete context that holds all multi-call data, including the
248 : * FuncCallContext itself
249 : */
5518 neilc 250 80735 : MemoryContextDelete(funcctx->multi_call_memory_ctx);
7598 bruce 251 80735 : }
252 :
253 :
254 : /*
255 : * get_call_result_type
256 : * Given a function's call info record, determine the kind of datatype
257 : * it is supposed to return. If resultTypeId isn't NULL, *resultTypeId
258 : * receives the actual datatype OID (this is mainly useful for scalar
259 : * result types). If resultTupleDesc isn't NULL, *resultTupleDesc
260 : * receives a pointer to a TupleDesc when the result is of a composite
261 : * type, or NULL when it's a scalar result.
262 : *
263 : * One hard case that this handles is resolution of actual rowtypes for
264 : * functions returning RECORD (from either the function's OUT parameter
265 : * list, or a ReturnSetInfo context node). TYPEFUNC_RECORD is returned
266 : * only when we couldn't resolve the actual rowtype for lack of information.
6583 tgl 267 ECB : *
268 : * The other hard case that this handles is resolution of polymorphism.
269 : * We will never return polymorphic pseudotypes (ANYELEMENT etc), either
270 : * as a scalar result type or as a component of a rowtype.
271 : *
272 : * This function is relatively expensive --- in a function returning set,
273 : * try to call it only the first time through.
274 : */
275 : TypeFuncClass
6583 tgl 276 GIC 33230 : get_call_result_type(FunctionCallInfo fcinfo,
277 : Oid *resultTypeId,
278 : TupleDesc *resultTupleDesc)
279 : {
280 66460 : return internal_get_result_type(fcinfo->flinfo->fn_oid,
281 33230 : fcinfo->flinfo->fn_expr,
282 33230 : (ReturnSetInfo *) fcinfo->resultinfo,
6583 tgl 283 ECB : resultTypeId,
284 : resultTupleDesc);
285 : }
286 :
287 : /*
288 : * get_expr_result_type
289 : * As above, but work from a calling expression node tree
290 : */
291 : TypeFuncClass
6583 tgl 292 GIC 279708 : get_expr_result_type(Node *expr,
293 : Oid *resultTypeId,
294 : TupleDesc *resultTupleDesc)
6583 tgl 295 ECB : {
296 : TypeFuncClass result;
297 :
6583 tgl 298 GIC 279708 : if (expr && IsA(expr, FuncExpr))
299 254703 : result = internal_get_result_type(((FuncExpr *) expr)->funcid,
300 : expr,
6583 tgl 301 ECB : NULL,
302 : resultTypeId,
303 : resultTupleDesc);
6558 tgl 304 GIC 25005 : else if (expr && IsA(expr, OpExpr))
6558 tgl 305 CBC 12 : result = internal_get_result_type(get_opcode(((OpExpr *) expr)->opno),
306 : expr,
6558 tgl 307 ECB : NULL,
308 : resultTypeId,
309 : resultTupleDesc);
1259 tgl 310 GIC 24993 : else if (expr && IsA(expr, RowExpr) &&
1259 tgl 311 CBC 30 : ((RowExpr *) expr)->row_typeid == RECORDOID)
1259 tgl 312 ECB : {
313 : /* We can resolve the record type by generating the tupdesc directly */
1259 tgl 314 GIC 30 : RowExpr *rexpr = (RowExpr *) expr;
1259 tgl 315 ECB : TupleDesc tupdesc;
1259 tgl 316 CBC 30 : AttrNumber i = 1;
317 : ListCell *lcc,
1259 tgl 318 ECB : *lcn;
319 :
1259 tgl 320 GIC 30 : tupdesc = CreateTemplateTupleDesc(list_length(rexpr->args));
321 30 : Assert(list_length(rexpr->args) == list_length(rexpr->colnames));
322 87 : forboth(lcc, rexpr->args, lcn, rexpr->colnames)
1259 tgl 323 ECB : {
1259 tgl 324 GIC 57 : Node *col = (Node *) lfirst(lcc);
1259 tgl 325 CBC 57 : char *colname = strVal(lfirst(lcn));
326 :
327 57 : TupleDescInitEntry(tupdesc, i,
1259 tgl 328 EUB : colname,
1259 tgl 329 ECB : exprType(col),
330 : exprTypmod(col),
331 : 0);
1259 tgl 332 GIC 57 : TupleDescInitEntryCollation(tupdesc, i,
1259 tgl 333 ECB : exprCollation(col));
1259 tgl 334 CBC 57 : i++;
1259 tgl 335 ECB : }
1259 tgl 336 GIC 30 : if (resultTypeId)
1259 tgl 337 UIC 0 : *resultTypeId = rexpr->row_typeid;
1259 tgl 338 GIC 30 : if (resultTupleDesc)
339 30 : *resultTupleDesc = BlessTupleDesc(tupdesc);
340 30 : return TYPEFUNC_COMPOSITE;
341 : }
175 342 24963 : else if (expr && IsA(expr, Const) &&
343 216 : ((Const *) expr)->consttype == RECORDOID &&
344 3 : !((Const *) expr)->constisnull)
345 : {
175 tgl 346 ECB : /*
347 : * When EXPLAIN'ing some queries with SEARCH/CYCLE clauses, we may
348 : * need to resolve field names of a RECORD-type Const. The datum
349 : * should contain a typmod that will tell us that.
175 tgl 350 EUB : */
175 tgl 351 ECB : HeapTupleHeader rec;
352 : Oid tupType;
353 : int32 tupTypmod;
354 :
175 tgl 355 CBC 3 : rec = DatumGetHeapTupleHeader(((Const *) expr)->constvalue);
175 tgl 356 GIC 3 : tupType = HeapTupleHeaderGetTypeId(rec);
175 tgl 357 CBC 3 : tupTypmod = HeapTupleHeaderGetTypMod(rec);
175 tgl 358 GIC 3 : if (resultTypeId)
175 tgl 359 UIC 0 : *resultTypeId = tupType;
175 tgl 360 GIC 3 : if (tupType != RECORDOID || tupTypmod >= 0)
361 : {
175 tgl 362 EUB : /* Should be able to look it up */
175 tgl 363 GBC 3 : if (resultTupleDesc)
364 3 : *resultTupleDesc = lookup_rowtype_tupdesc_copy(tupType,
365 : tupTypmod);
175 tgl 366 GIC 3 : return TYPEFUNC_COMPOSITE;
367 : }
368 : else
369 : {
175 tgl 370 ECB : /* This shouldn't really happen ... */
175 tgl 371 UIC 0 : if (resultTupleDesc)
372 0 : *resultTupleDesc = NULL;
175 tgl 373 LBC 0 : return TYPEFUNC_RECORD;
175 tgl 374 ECB : }
375 : }
6583 376 : else
377 : {
378 : /* handle as a generic expression; no chance to resolve RECORD */
6385 bruce 379 CBC 24960 : Oid typid = exprType(expr);
380 : Oid base_typid;
6583 tgl 381 ECB :
6583 tgl 382 GIC 24960 : if (resultTypeId)
383 228 : *resultTypeId = typid;
6583 tgl 384 CBC 24960 : if (resultTupleDesc)
6583 tgl 385 GIC 24960 : *resultTupleDesc = NULL;
1991 386 24960 : result = get_type_func_class(typid, &base_typid);
387 24960 : if ((result == TYPEFUNC_COMPOSITE ||
388 24758 : result == TYPEFUNC_COMPOSITE_DOMAIN) &&
389 : resultTupleDesc)
390 24758 : *resultTupleDesc = lookup_rowtype_tupdesc_copy(base_typid, -1);
391 : }
392 :
6583 393 279675 : return result;
6583 tgl 394 ECB : }
395 :
396 : /*
397 : * get_func_result_type
398 : * As above, but work from a function's OID only
399 : *
400 : * This will not be able to resolve pure-RECORD results nor polymorphism.
401 : */
402 : TypeFuncClass
6583 tgl 403 GIC 17793 : get_func_result_type(Oid functionId,
404 : Oid *resultTypeId,
405 : TupleDesc *resultTupleDesc)
406 : {
407 17793 : return internal_get_result_type(functionId,
408 : NULL,
409 : NULL,
410 : resultTypeId,
411 : resultTupleDesc);
412 : }
413 :
6583 tgl 414 ECB : /*
415 : * internal_get_result_type -- workhorse code implementing all the above
416 : *
417 : * funcid must always be supplied. call_expr and rsinfo can be NULL if not
418 : * available. We will return TYPEFUNC_RECORD, and store NULL into
419 : * *resultTupleDesc, if we cannot deduce the complete result rowtype from
420 : * the available information.
421 : */
422 : static TypeFuncClass
6583 tgl 423 GIC 305738 : internal_get_result_type(Oid funcid,
424 : Node *call_expr,
425 : ReturnSetInfo *rsinfo,
426 : Oid *resultTypeId,
427 : TupleDesc *resultTupleDesc)
6583 tgl 428 ECB : {
429 : TypeFuncClass result;
6583 tgl 430 EUB : HeapTuple tp;
6583 tgl 431 ECB : Form_pg_proc procform;
432 : Oid rettype;
1991 433 : Oid base_rettype;
434 : TupleDesc tupdesc;
435 :
6583 436 : /* First fetch the function's pg_proc row to inspect its rettype */
4802 rhaas 437 CBC 305738 : tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
6583 tgl 438 GIC 305738 : if (!HeapTupleIsValid(tp))
6583 tgl 439 UIC 0 : elog(ERROR, "cache lookup failed for function %u", funcid);
6583 tgl 440 GIC 305738 : procform = (Form_pg_proc) GETSTRUCT(tp);
441 :
442 305738 : rettype = procform->prorettype;
443 :
6583 tgl 444 ECB : /* Check for OUT parameters defining a RECORD result */
6583 tgl 445 CBC 305738 : tupdesc = build_function_result_tupdesc_t(tp);
6583 tgl 446 GIC 305738 : if (tupdesc)
6583 tgl 447 ECB : {
448 : /*
449 : * It has OUT parameters, so it's basically like a regular composite
450 : * type, except we have to be able to resolve any polymorphic OUT
6385 bruce 451 : * parameters.
6583 tgl 452 : */
6583 tgl 453 CBC 244028 : if (resultTypeId)
454 43363 : *resultTypeId = rettype;
6583 tgl 455 ECB :
6583 tgl 456 CBC 244028 : if (resolve_polymorphic_tupdesc(tupdesc,
457 : &procform->proargtypes,
458 : call_expr))
459 : {
6583 tgl 460 GBC 244028 : if (tupdesc->tdtypeid == RECORDOID &&
461 244028 : tupdesc->tdtypmod < 0)
462 244028 : assign_record_type_typmod(tupdesc);
6583 tgl 463 GIC 244028 : if (resultTupleDesc)
464 244028 : *resultTupleDesc = tupdesc;
6583 tgl 465 CBC 244028 : result = TYPEFUNC_COMPOSITE;
466 : }
6583 tgl 467 ECB : else
468 : {
6583 tgl 469 UIC 0 : if (resultTupleDesc)
470 0 : *resultTupleDesc = NULL;
471 0 : result = TYPEFUNC_RECORD;
472 : }
6583 tgl 473 ECB :
6583 tgl 474 GIC 244028 : ReleaseSysCache(tp);
6583 tgl 475 ECB :
6583 tgl 476 GIC 244028 : return result;
6583 tgl 477 ECB : }
6583 tgl 478 EUB :
479 : /*
480 : * If scalar polymorphic result, try to resolve it.
481 : */
5851 tgl 482 GIC 61710 : if (IsPolymorphicType(rettype))
6583 tgl 483 ECB : {
6385 bruce 484 GIC 7978 : Oid newrettype = exprType(call_expr);
485 :
6583 tgl 486 CBC 7978 : if (newrettype == InvalidOid) /* this probably should not happen */
6583 tgl 487 LBC 0 : ereport(ERROR,
6583 tgl 488 ECB : (errcode(ERRCODE_DATATYPE_MISMATCH),
489 : errmsg("could not determine actual result type for function \"%s\" declared to return type %s",
490 : NameStr(procform->proname),
491 : format_type_be(rettype))));
6583 tgl 492 CBC 7978 : rettype = newrettype;
6583 tgl 493 ECB : }
494 :
6583 tgl 495 CBC 61710 : if (resultTypeId)
6583 tgl 496 GIC 54635 : *resultTypeId = rettype;
6583 tgl 497 CBC 61710 : if (resultTupleDesc)
6385 bruce 498 61710 : *resultTupleDesc = NULL; /* default result */
499 :
6583 tgl 500 ECB : /* Classify the result type */
1991 tgl 501 CBC 61710 : result = get_type_func_class(rettype, &base_rettype);
6583 502 61710 : switch (result)
6583 tgl 503 ECB : {
6583 tgl 504 GIC 2842 : case TYPEFUNC_COMPOSITE:
1991 tgl 505 ECB : case TYPEFUNC_COMPOSITE_DOMAIN:
6583 tgl 506 CBC 2842 : if (resultTupleDesc)
1991 tgl 507 GIC 2842 : *resultTupleDesc = lookup_rowtype_tupdesc_copy(base_rettype, -1);
6583 tgl 508 ECB : /* Named composite types can't have any polymorphic columns */
6583 tgl 509 CBC 2842 : break;
510 57675 : case TYPEFUNC_SCALAR:
6583 tgl 511 GIC 57675 : break;
512 1187 : case TYPEFUNC_RECORD:
6583 tgl 513 ECB : /* We must get the tupledesc from call context */
6583 tgl 514 CBC 1187 : if (rsinfo && IsA(rsinfo, ReturnSetInfo) &&
515 290 : rsinfo->expectedDesc != NULL)
516 : {
6583 tgl 517 GIC 267 : result = TYPEFUNC_COMPOSITE;
6583 tgl 518 CBC 267 : if (resultTupleDesc)
6583 tgl 519 GIC 267 : *resultTupleDesc = rsinfo->expectedDesc;
6583 tgl 520 ECB : /* Assume no polymorphic columns here, either */
521 : }
6583 tgl 522 GIC 1187 : break;
523 6 : default:
524 6 : break;
525 : }
526 :
527 61710 : ReleaseSysCache(tp);
528 :
529 61710 : return result;
530 : }
531 :
532 : /*
533 : * get_expr_result_tupdesc
1991 tgl 534 ECB : * Get a tupdesc describing the result of a composite-valued expression
535 : *
536 : * If expression is not composite or rowtype can't be determined, returns NULL
537 : * if noError is true, else throws error.
538 : *
539 : * This is a simpler version of get_expr_result_type() for use when the caller
540 : * is only interested in determinate rowtype results.
541 : */
542 : TupleDesc
1991 tgl 543 CBC 205843 : get_expr_result_tupdesc(Node *expr, bool noError)
544 : {
1991 tgl 545 ECB : TupleDesc tupleDesc;
546 : TypeFuncClass functypclass;
1991 tgl 547 EUB :
1991 tgl 548 GIC 205843 : functypclass = get_expr_result_type(expr, NULL, &tupleDesc);
1991 tgl 549 EUB :
1991 tgl 550 GBC 205843 : if (functypclass == TYPEFUNC_COMPOSITE ||
551 : functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
1991 tgl 552 GIC 204959 : return tupleDesc;
553 :
554 884 : if (!noError)
1991 tgl 555 EUB : {
1991 tgl 556 UIC 0 : Oid exprTypeId = exprType(expr);
557 :
558 0 : if (exprTypeId != RECORDOID)
559 0 : ereport(ERROR,
1991 tgl 560 ECB : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
561 : errmsg("type %s is not composite",
562 : format_type_be(exprTypeId))));
563 : else
1991 tgl 564 UIC 0 : ereport(ERROR,
565 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
566 : errmsg("record type has not been registered")));
567 : }
568 :
1991 tgl 569 GIC 884 : return NULL;
570 : }
571 :
1121 tgl 572 ECB : /*
573 : * Resolve actual type of ANYELEMENT from other polymorphic inputs
574 : *
575 : * Note: the error cases here and in the sibling functions below are not
576 : * really user-facing; they could only occur if the function signature is
577 : * incorrect or the parser failed to enforce consistency of the actual
578 : * argument types. Hence, we don't sweat too much over the error messages.
579 : */
580 : static void
1121 tgl 581 GBC 5847 : resolve_anyelement_from_others(polymorphic_actuals *actuals)
582 : {
1121 tgl 583 GIC 5847 : if (OidIsValid(actuals->anyarray_type))
584 : {
585 : /* Use the element type corresponding to actual type */
1121 tgl 586 CBC 5763 : Oid array_base_type = getBaseType(actuals->anyarray_type);
1121 tgl 587 GIC 5763 : Oid array_typelem = get_element_type(array_base_type);
1121 tgl 588 ECB :
1121 tgl 589 GIC 5763 : if (!OidIsValid(array_typelem))
1121 tgl 590 UIC 0 : ereport(ERROR,
1121 tgl 591 ECB : (errcode(ERRCODE_DATATYPE_MISMATCH),
592 : errmsg("argument declared %s is not an array but type %s",
593 : "anyarray",
594 : format_type_be(array_base_type))));
1121 tgl 595 GBC 5763 : actuals->anyelement_type = array_typelem;
596 : }
1121 tgl 597 GIC 84 : else if (OidIsValid(actuals->anyrange_type))
598 : {
599 : /* Use the element type corresponding to actual type */
1121 tgl 600 CBC 66 : Oid range_base_type = getBaseType(actuals->anyrange_type);
1121 tgl 601 GIC 66 : Oid range_typelem = get_range_subtype(range_base_type);
1121 tgl 602 ECB :
1121 tgl 603 GIC 66 : if (!OidIsValid(range_typelem))
1121 tgl 604 UIC 0 : ereport(ERROR,
605 : (errcode(ERRCODE_DATATYPE_MISMATCH),
606 : errmsg("argument declared %s is not a range type but type %s",
607 : "anyrange",
608 : format_type_be(range_base_type))));
1121 tgl 609 GIC 66 : actuals->anyelement_type = range_typelem;
1121 tgl 610 ECB : }
840 akorotkov 611 CBC 18 : else if (OidIsValid(actuals->anymultirange_type))
840 akorotkov 612 ECB : {
840 akorotkov 613 EUB : /* Use the element type based on the multirange type */
614 : Oid multirange_base_type;
615 : Oid multirange_typelem;
616 : Oid range_base_type;
617 : Oid range_typelem;
618 :
840 akorotkov 619 CBC 18 : multirange_base_type = getBaseType(actuals->anymultirange_type);
620 18 : multirange_typelem = get_multirange_range(multirange_base_type);
840 akorotkov 621 GIC 18 : if (!OidIsValid(multirange_typelem))
840 akorotkov 622 LBC 0 : ereport(ERROR,
840 akorotkov 623 EUB : (errcode(ERRCODE_DATATYPE_MISMATCH),
624 : errmsg("argument declared %s is not a multirange type but type %s",
625 : "anymultirange",
626 : format_type_be(multirange_base_type))));
627 :
840 akorotkov 628 CBC 18 : range_base_type = getBaseType(multirange_typelem);
840 akorotkov 629 GIC 18 : range_typelem = get_range_subtype(range_base_type);
630 :
840 akorotkov 631 GBC 18 : if (!OidIsValid(range_typelem))
840 akorotkov 632 LBC 0 : ereport(ERROR,
633 : (errcode(ERRCODE_DATATYPE_MISMATCH),
634 : errmsg("argument declared %s does not contain a range type but type %s",
635 : "anymultirange",
636 : format_type_be(range_base_type))));
840 akorotkov 637 GIC 18 : actuals->anyelement_type = range_typelem;
840 akorotkov 638 ECB : }
639 : else
1121 tgl 640 UIC 0 : elog(ERROR, "could not determine polymorphic type");
1121 tgl 641 CBC 5847 : }
1121 tgl 642 ECB :
643 : /*
644 : * Resolve actual type of ANYARRAY from other polymorphic inputs
645 : */
646 : static void
1121 tgl 647 CBC 156 : resolve_anyarray_from_others(polymorphic_actuals *actuals)
648 : {
1121 tgl 649 ECB : /* If we don't know ANYELEMENT, resolve that first */
1121 tgl 650 GBC 156 : if (!OidIsValid(actuals->anyelement_type))
1121 tgl 651 GIC 27 : resolve_anyelement_from_others(actuals);
652 :
653 156 : if (OidIsValid(actuals->anyelement_type))
1121 tgl 654 ECB : {
655 : /* Use the array type corresponding to actual type */
1121 tgl 656 GIC 156 : Oid array_typeid = get_array_type(actuals->anyelement_type);
1121 tgl 657 EUB :
1121 tgl 658 CBC 156 : if (!OidIsValid(array_typeid))
1121 tgl 659 UIC 0 : ereport(ERROR,
660 : (errcode(ERRCODE_UNDEFINED_OBJECT),
661 : errmsg("could not find array type for data type %s",
662 : format_type_be(actuals->anyelement_type))));
1121 tgl 663 GIC 156 : actuals->anyarray_type = array_typeid;
1121 tgl 664 ECB : }
665 : else
1121 tgl 666 UIC 0 : elog(ERROR, "could not determine polymorphic type");
1121 tgl 667 GIC 156 : }
668 :
669 : /*
670 : * Resolve actual type of ANYRANGE from other polymorphic inputs
1121 tgl 671 ECB : */
672 : static void
1121 tgl 673 GIC 9 : resolve_anyrange_from_others(polymorphic_actuals *actuals)
1121 tgl 674 ECB : {
675 : /*
676 : * We can't deduce a range type from other polymorphic array or base
840 akorotkov 677 : * types, because there may be multiple range types with the same subtype,
840 akorotkov 678 EUB : * but we can deduce it from a polymorphic multirange type.
679 : */
840 akorotkov 680 GIC 9 : if (OidIsValid(actuals->anymultirange_type))
681 : {
682 : /* Use the element type based on the multirange type */
840 akorotkov 683 CBC 9 : Oid multirange_base_type = getBaseType(actuals->anymultirange_type);
840 akorotkov 684 GIC 9 : Oid multirange_typelem = get_multirange_range(multirange_base_type);
685 :
840 akorotkov 686 GBC 9 : if (!OidIsValid(multirange_typelem))
840 akorotkov 687 LBC 0 : ereport(ERROR,
688 : (errcode(ERRCODE_DATATYPE_MISMATCH),
689 : errmsg("argument declared %s is not a multirange type but type %s",
690 : "anymultirange",
691 : format_type_be(multirange_base_type))));
840 akorotkov 692 GIC 9 : actuals->anyrange_type = multirange_typelem;
840 akorotkov 693 ECB : }
694 : else
840 akorotkov 695 UIC 0 : elog(ERROR, "could not determine polymorphic type");
840 akorotkov 696 GIC 9 : }
697 :
698 : /*
699 : * Resolve actual type of ANYMULTIRANGE from other polymorphic inputs
840 akorotkov 700 ECB : */
701 : static void
840 akorotkov 702 CBC 9 : resolve_anymultirange_from_others(polymorphic_actuals *actuals)
840 akorotkov 703 ECB : {
704 : /*
705 : * We can't deduce a multirange type from polymorphic array or base types,
840 akorotkov 706 EUB : * because there may be multiple range types with the same subtype, but we
707 : * can deduce it from a polymorphic range type.
708 : */
840 akorotkov 709 GIC 9 : if (OidIsValid(actuals->anyrange_type))
840 akorotkov 710 ECB : {
840 akorotkov 711 GIC 9 : Oid range_base_type = getBaseType(actuals->anyrange_type);
712 9 : Oid multirange_typeid = get_range_multirange(range_base_type);
840 akorotkov 713 EUB :
840 akorotkov 714 CBC 9 : if (!OidIsValid(multirange_typeid))
840 akorotkov 715 UIC 0 : ereport(ERROR,
716 : (errcode(ERRCODE_UNDEFINED_OBJECT),
717 : errmsg("could not find multirange type for data type %s",
718 : format_type_be(actuals->anyrange_type))));
840 akorotkov 719 GIC 9 : actuals->anymultirange_type = multirange_typeid;
720 : }
721 : else
840 akorotkov 722 UIC 0 : elog(ERROR, "could not determine polymorphic type");
1121 tgl 723 GIC 9 : }
724 :
725 : /*
726 : * Given the result tuple descriptor for a function with OUT parameters,
1121 tgl 727 ECB : * replace any polymorphic column types (ANYELEMENT etc) in the tupdesc
728 : * with concrete data types deduced from the input arguments.
729 : * declared_args is an oidvector of the function's declared input arg types
730 : * (showing which are polymorphic), and call_expr is the call expression.
1116 731 : *
732 : * Returns true if able to deduce all types, false if necessary information
733 : * is not provided (call_expr is NULL or arg types aren't identifiable).
6583 734 : */
735 : static bool
6583 tgl 736 CBC 244028 : resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
6583 tgl 737 ECB : Node *call_expr)
738 : {
6583 tgl 739 CBC 244028 : int natts = tupdesc->natts;
740 244028 : int nargs = declared_args->dim1;
1121 tgl 741 GIC 244028 : bool have_polymorphic_result = false;
6583 742 244028 : bool have_anyelement_result = false;
6583 tgl 743 CBC 244028 : bool have_anyarray_result = false;
4175 heikki.linnakangas 744 244028 : bool have_anyrange_result = false;
840 akorotkov 745 GIC 244028 : bool have_anymultirange_result = false;
1116 tgl 746 244028 : bool have_anycompatible_result = false;
747 244028 : bool have_anycompatible_array_result = false;
1116 tgl 748 CBC 244028 : bool have_anycompatible_range_result = false;
840 akorotkov 749 GIC 244028 : bool have_anycompatible_multirange_result = false;
1121 tgl 750 ECB : polymorphic_actuals poly_actuals;
751 : polymorphic_actuals anyc_actuals;
4175 heikki.linnakangas 752 CBC 244028 : Oid anycollation = InvalidOid;
1116 tgl 753 GIC 244028 : Oid anycompatcollation = InvalidOid;
754 : int i;
6583 tgl 755 ECB :
756 : /* See if there are any polymorphic outputs; quick out if not */
6583 tgl 757 CBC 3673144 : for (i = 0; i < natts; i++)
6583 tgl 758 ECB : {
2058 andres 759 CBC 3429116 : switch (TupleDescAttr(tupdesc, i)->atttypid)
6583 tgl 760 ECB : {
6583 tgl 761 CBC 5844 : case ANYELEMENTOID:
1121 tgl 762 ECB : case ANYNONARRAYOID:
763 : case ANYENUMOID:
1121 tgl 764 CBC 5844 : have_polymorphic_result = true;
6583 765 5844 : have_anyelement_result = true;
766 5844 : break;
767 126 : case ANYARRAYOID:
1121 768 126 : have_polymorphic_result = true;
6583 769 126 : have_anyarray_result = true;
770 126 : break;
4175 heikki.linnakangas 771 GIC 27 : case ANYRANGEOID:
1121 tgl 772 CBC 27 : have_polymorphic_result = true;
4175 heikki.linnakangas 773 27 : have_anyrange_result = true;
774 27 : break;
840 akorotkov 775 36 : case ANYMULTIRANGEOID:
776 36 : have_polymorphic_result = true;
777 36 : have_anymultirange_result = true;
778 36 : break;
1116 tgl 779 45 : case ANYCOMPATIBLEOID:
1116 tgl 780 ECB : case ANYCOMPATIBLENONARRAYOID:
1116 tgl 781 CBC 45 : have_polymorphic_result = true;
782 45 : have_anycompatible_result = true;
1116 tgl 783 GBC 45 : break;
784 99 : case ANYCOMPATIBLEARRAYOID:
785 99 : have_polymorphic_result = true;
786 99 : have_anycompatible_array_result = true;
1116 tgl 787 CBC 99 : break;
788 9 : case ANYCOMPATIBLERANGEOID:
1116 tgl 789 GIC 9 : have_polymorphic_result = true;
790 9 : have_anycompatible_range_result = true;
1116 tgl 791 CBC 9 : break;
840 akorotkov 792 LBC 0 : case ANYCOMPATIBLEMULTIRANGEOID:
840 akorotkov 793 UIC 0 : have_polymorphic_result = true;
794 0 : have_anycompatible_multirange_result = true;
795 0 : break;
6583 tgl 796 GIC 3422930 : default:
797 3422930 : break;
798 : }
799 : }
1121 800 244028 : if (!have_polymorphic_result)
6583 tgl 801 CBC 238031 : return true;
6583 tgl 802 EUB :
803 : /*
3260 bruce 804 ECB : * Otherwise, extract actual datatype(s) from input arguments. (We assume
1116 tgl 805 : * the parser already validated consistency of the arguments. Also, for
806 : * the ANYCOMPATIBLE pseudotype family, we expect that all matching
807 : * arguments were coerced to the selected common supertype, so that it
808 : * doesn't matter which one's exposed type we look at.)
6583 809 : */
6583 tgl 810 GIC 5997 : if (!call_expr)
6583 tgl 811 LBC 0 : return false; /* no hope */
812 :
1121 tgl 813 GIC 5997 : memset(&poly_actuals, 0, sizeof(poly_actuals));
1116 tgl 814 CBC 5997 : memset(&anyc_actuals, 0, sizeof(anyc_actuals));
815 :
6583 816 12183 : for (i = 0; i < nargs; i++)
6583 tgl 817 ECB : {
6583 tgl 818 CBC 6186 : switch (declared_args->values[i])
6583 tgl 819 EUB : {
6583 tgl 820 GIC 99 : case ANYELEMENTOID:
5786 tgl 821 ECB : case ANYNONARRAYOID:
5851 822 : case ANYENUMOID:
1121 tgl 823 CBC 99 : if (!OidIsValid(poly_actuals.anyelement_type))
824 : {
825 99 : poly_actuals.anyelement_type =
826 99 : get_call_expr_argtype(call_expr, i);
827 99 : if (!OidIsValid(poly_actuals.anyelement_type))
1121 tgl 828 UBC 0 : return false;
829 : }
6583 tgl 830 CBC 99 : break;
831 5817 : case ANYARRAYOID:
1121 832 5817 : if (!OidIsValid(poly_actuals.anyarray_type))
833 : {
834 5817 : poly_actuals.anyarray_type =
835 5817 : get_call_expr_argtype(call_expr, i);
836 5817 : if (!OidIsValid(poly_actuals.anyarray_type))
1121 tgl 837 UBC 0 : return false;
838 : }
6583 tgl 839 CBC 5817 : break;
4175 heikki.linnakangas 840 54 : case ANYRANGEOID:
1121 tgl 841 54 : if (!OidIsValid(poly_actuals.anyrange_type))
842 : {
843 54 : poly_actuals.anyrange_type =
844 54 : get_call_expr_argtype(call_expr, i);
845 54 : if (!OidIsValid(poly_actuals.anyrange_type))
1121 tgl 846 UBC 0 : return false;
847 : }
4175 heikki.linnakangas 848 CBC 54 : break;
840 akorotkov 849 45 : case ANYMULTIRANGEOID:
840 akorotkov 850 GIC 45 : if (!OidIsValid(poly_actuals.anymultirange_type))
840 akorotkov 851 ECB : {
840 akorotkov 852 GIC 45 : poly_actuals.anymultirange_type =
840 akorotkov 853 CBC 45 : get_call_expr_argtype(call_expr, i);
854 45 : if (!OidIsValid(poly_actuals.anymultirange_type))
840 akorotkov 855 LBC 0 : return false;
840 akorotkov 856 EUB : }
840 akorotkov 857 GIC 45 : break;
1116 tgl 858 CBC 126 : case ANYCOMPATIBLEOID:
1116 tgl 859 ECB : case ANYCOMPATIBLENONARRAYOID:
1116 tgl 860 CBC 126 : if (!OidIsValid(anyc_actuals.anyelement_type))
861 : {
862 72 : anyc_actuals.anyelement_type =
863 72 : get_call_expr_argtype(call_expr, i);
864 72 : if (!OidIsValid(anyc_actuals.anyelement_type))
1116 tgl 865 UBC 0 : return false;
866 : }
1116 tgl 867 CBC 126 : break;
868 18 : case ANYCOMPATIBLEARRAYOID:
869 18 : if (!OidIsValid(anyc_actuals.anyarray_type))
870 : {
871 18 : anyc_actuals.anyarray_type =
872 18 : get_call_expr_argtype(call_expr, i);
873 18 : if (!OidIsValid(anyc_actuals.anyarray_type))
1116 tgl 874 UBC 0 : return false;
875 : }
1116 tgl 876 CBC 18 : break;
1116 tgl 877 GBC 27 : case ANYCOMPATIBLERANGEOID:
878 27 : if (!OidIsValid(anyc_actuals.anyrange_type))
879 : {
880 27 : anyc_actuals.anyrange_type =
881 27 : get_call_expr_argtype(call_expr, i);
882 27 : if (!OidIsValid(anyc_actuals.anyrange_type))
1116 tgl 883 UBC 0 : return false;
884 : }
1116 tgl 885 GBC 27 : break;
840 akorotkov 886 UBC 0 : case ANYCOMPATIBLEMULTIRANGEOID:
887 0 : if (!OidIsValid(anyc_actuals.anymultirange_type))
888 : {
840 akorotkov 889 UIC 0 : anyc_actuals.anymultirange_type =
890 0 : get_call_expr_argtype(call_expr, i);
891 0 : if (!OidIsValid(anyc_actuals.anymultirange_type))
840 akorotkov 892 LBC 0 : return false;
840 akorotkov 893 ECB : }
840 akorotkov 894 UIC 0 : break;
6583 tgl 895 LBC 0 : default:
896 0 : break;
897 : }
6583 tgl 898 ECB : }
899 :
900 : /* If needed, deduce one polymorphic type from others */
1121 tgl 901 CBC 5997 : if (have_anyelement_result && !OidIsValid(poly_actuals.anyelement_type))
902 5790 : resolve_anyelement_from_others(&poly_actuals);
903 :
904 5997 : if (have_anyarray_result && !OidIsValid(poly_actuals.anyarray_type))
905 63 : resolve_anyarray_from_others(&poly_actuals);
906 :
907 5997 : if (have_anyrange_result && !OidIsValid(poly_actuals.anyrange_type))
908 9 : resolve_anyrange_from_others(&poly_actuals);
909 :
840 akorotkov 910 5997 : if (have_anymultirange_result && !OidIsValid(poly_actuals.anymultirange_type))
840 akorotkov 911 GBC 9 : resolve_anymultirange_from_others(&poly_actuals);
912 :
1116 tgl 913 CBC 5997 : if (have_anycompatible_result && !OidIsValid(anyc_actuals.anyelement_type))
1116 tgl 914 GBC 27 : resolve_anyelement_from_others(&anyc_actuals);
915 :
1116 tgl 916 GIC 5997 : if (have_anycompatible_array_result && !OidIsValid(anyc_actuals.anyarray_type))
917 81 : resolve_anyarray_from_others(&anyc_actuals);
918 :
919 5997 : if (have_anycompatible_range_result && !OidIsValid(anyc_actuals.anyrange_type))
1116 tgl 920 UIC 0 : resolve_anyrange_from_others(&anyc_actuals);
921 :
840 akorotkov 922 GIC 5997 : if (have_anycompatible_multirange_result && !OidIsValid(anyc_actuals.anymultirange_type))
840 akorotkov 923 LBC 0 : resolve_anymultirange_from_others(&anyc_actuals);
840 akorotkov 924 ECB :
4404 tgl 925 : /*
4382 bruce 926 EUB : * Identify the collation to use for polymorphic OUT parameters. (It'll
927 : * necessarily be the same for both anyelement and anyarray, likewise for
1116 tgl 928 ECB : * anycompatible and anycompatiblearray.) Note that range types are not
929 : * collatable, so any possible internal collation of a range type is not
930 : * considered here.
4404 tgl 931 EUB : */
1121 tgl 932 GIC 5997 : if (OidIsValid(poly_actuals.anyelement_type))
1121 tgl 933 CBC 5916 : anycollation = get_typcollation(poly_actuals.anyelement_type);
1121 tgl 934 GIC 81 : else if (OidIsValid(poly_actuals.anyarray_type))
1121 tgl 935 UIC 0 : anycollation = get_typcollation(poly_actuals.anyarray_type);
936 :
1116 tgl 937 GIC 5997 : if (OidIsValid(anyc_actuals.anyelement_type))
938 99 : anycompatcollation = get_typcollation(anyc_actuals.anyelement_type);
939 5898 : else if (OidIsValid(anyc_actuals.anyarray_type))
1116 tgl 940 LBC 0 : anycompatcollation = get_typcollation(anyc_actuals.anyarray_type);
941 :
1116 tgl 942 CBC 5997 : if (OidIsValid(anycollation) || OidIsValid(anycompatcollation))
943 : {
4404 tgl 944 ECB : /*
945 : * The types are collatable, so consider whether to use a nondefault
946 : * collation. We do so if we can identify the input collation used
4404 tgl 947 EUB : * for the function.
948 : */
4382 bruce 949 GIC 33 : Oid inputcollation = exprInputCollation(call_expr);
950 :
4404 tgl 951 33 : if (OidIsValid(inputcollation))
1116 tgl 952 ECB : {
1116 tgl 953 GIC 21 : if (OidIsValid(anycollation))
1116 tgl 954 CBC 21 : anycollation = inputcollation;
1116 tgl 955 GIC 21 : if (OidIsValid(anycompatcollation))
1116 tgl 956 LBC 0 : anycompatcollation = inputcollation;
957 : }
4404 tgl 958 ECB : }
959 :
960 : /* And finally replace the tuple column types as needed */
6583 tgl 961 CBC 18000 : for (i = 0; i < natts; i++)
6583 tgl 962 ECB : {
2058 andres 963 GIC 12003 : Form_pg_attribute att = TupleDescAttr(tupdesc, i);
964 :
965 12003 : switch (att->atttypid)
6583 tgl 966 ECB : {
6583 tgl 967 CBC 5844 : case ANYELEMENTOID:
5786 tgl 968 ECB : case ANYNONARRAYOID:
5851 969 : case ANYENUMOID:
6385 bruce 970 CBC 5844 : TupleDescInitEntry(tupdesc, i + 1,
2058 andres 971 GIC 5844 : NameStr(att->attname),
972 : poly_actuals.anyelement_type,
973 : -1,
6583 tgl 974 ECB : 0);
4404 tgl 975 CBC 5844 : TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
6583 976 5844 : break;
977 126 : case ANYARRAYOID:
6385 bruce 978 126 : TupleDescInitEntry(tupdesc, i + 1,
2058 andres 979 GIC 126 : NameStr(att->attname),
980 : poly_actuals.anyarray_type,
981 : -1,
982 : 0);
4404 tgl 983 CBC 126 : TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
6583 984 126 : break;
4175 heikki.linnakangas 985 27 : case ANYRANGEOID:
986 27 : TupleDescInitEntry(tupdesc, i + 1,
2058 andres 987 GIC 27 : NameStr(att->attname),
988 : poly_actuals.anyrange_type,
989 : -1,
990 : 0);
4158 tgl 991 ECB : /* no collation should be attached to a range type */
4175 heikki.linnakangas 992 CBC 27 : break;
840 akorotkov 993 GIC 36 : case ANYMULTIRANGEOID:
840 akorotkov 994 CBC 36 : TupleDescInitEntry(tupdesc, i + 1,
995 36 : NameStr(att->attname),
996 : poly_actuals.anymultirange_type,
997 : -1,
998 : 0);
840 akorotkov 999 ECB : /* no collation should be attached to a multirange type */
840 akorotkov 1000 CBC 36 : break;
1116 tgl 1001 45 : case ANYCOMPATIBLEOID:
1116 tgl 1002 ECB : case ANYCOMPATIBLENONARRAYOID:
1116 tgl 1003 CBC 45 : TupleDescInitEntry(tupdesc, i + 1,
1116 tgl 1004 GIC 45 : NameStr(att->attname),
1005 : anyc_actuals.anyelement_type,
1006 : -1,
1116 tgl 1007 ECB : 0);
1116 tgl 1008 CBC 45 : TupleDescInitEntryCollation(tupdesc, i + 1, anycompatcollation);
1009 45 : break;
1010 99 : case ANYCOMPATIBLEARRAYOID:
1011 99 : TupleDescInitEntry(tupdesc, i + 1,
1116 tgl 1012 GIC 99 : NameStr(att->attname),
1013 : anyc_actuals.anyarray_type,
1014 : -1,
1015 : 0);
1116 tgl 1016 CBC 99 : TupleDescInitEntryCollation(tupdesc, i + 1, anycompatcollation);
1116 tgl 1017 GBC 99 : break;
1018 9 : case ANYCOMPATIBLERANGEOID:
1019 9 : TupleDescInitEntry(tupdesc, i + 1,
1116 tgl 1020 GIC 9 : NameStr(att->attname),
1021 : anyc_actuals.anyrange_type,
1022 : -1,
1023 : 0);
1116 tgl 1024 EUB : /* no collation should be attached to a range type */
1116 tgl 1025 CBC 9 : break;
840 akorotkov 1026 LBC 0 : case ANYCOMPATIBLEMULTIRANGEOID:
840 akorotkov 1027 UIC 0 : TupleDescInitEntry(tupdesc, i + 1,
1028 0 : NameStr(att->attname),
1029 : anyc_actuals.anymultirange_type,
840 akorotkov 1030 ECB : -1,
1031 : 0);
1032 : /* no collation should be attached to a multirange type */
840 akorotkov 1033 UIC 0 : break;
6583 tgl 1034 GIC 5817 : default:
1035 5817 : break;
1036 : }
1037 : }
1038 :
1039 5997 : return true;
1040 : }
1041 :
1042 : /*
1043 : * Given the declared argument types and modes for a function, replace any
1044 : * polymorphic types (ANYELEMENT etc) in argtypes[] with concrete data types
1045 : * deduced from the input arguments found in call_expr.
1046 : *
1116 tgl 1047 ECB : * Returns true if able to deduce all types, false if necessary information
1048 : * is not provided (call_expr is NULL or arg types aren't identifiable).
1049 : *
5786 1050 : * This is the same logic as resolve_polymorphic_tupdesc, but with a different
1121 1051 : * argument representation, and slightly different output responsibilities.
6578 1052 : *
1053 : * argmodes may be NULL, in which case all arguments are assumed to be IN mode.
1054 : */
1055 : bool
6578 tgl 1056 CBC 6113 : resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
6578 tgl 1057 ECB : Node *call_expr)
1058 : {
1121 tgl 1059 GIC 6113 : bool have_polymorphic_result = false;
6578 1060 6113 : bool have_anyelement_result = false;
1061 6113 : bool have_anyarray_result = false;
4175 heikki.linnakangas 1062 6113 : bool have_anyrange_result = false;
840 akorotkov 1063 6113 : bool have_anymultirange_result = false;
1116 tgl 1064 6113 : bool have_anycompatible_result = false;
1065 6113 : bool have_anycompatible_array_result = false;
1066 6113 : bool have_anycompatible_range_result = false;
840 akorotkov 1067 6113 : bool have_anycompatible_multirange_result = false;
1068 : polymorphic_actuals poly_actuals;
1116 tgl 1069 ECB : polymorphic_actuals anyc_actuals;
6578 1070 : int inargno;
1071 : int i;
1072 :
1073 : /*
1121 1074 : * First pass: resolve polymorphic inputs, check for outputs. As in
1075 : * resolve_polymorphic_tupdesc, we rely on the parser to have enforced
1116 1076 : * type consistency and coerced ANYCOMPATIBLE args to a common supertype.
1077 : */
1121 tgl 1078 CBC 6113 : memset(&poly_actuals, 0, sizeof(poly_actuals));
1116 tgl 1079 GIC 6113 : memset(&anyc_actuals, 0, sizeof(anyc_actuals));
6578 1080 6113 : inargno = 0;
6578 tgl 1081 CBC 14782 : for (i = 0; i < numargs; i++)
1082 : {
6385 bruce 1083 8669 : char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
6578 tgl 1084 ECB :
6578 tgl 1085 GIC 8669 : switch (argtypes[i])
1086 : {
1087 721 : case ANYELEMENTOID:
5786 tgl 1088 ECB : case ANYNONARRAYOID:
1089 : case ANYENUMOID:
5378 tgl 1090 CBC 721 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
1121 tgl 1091 ECB : {
1121 tgl 1092 CBC 3 : have_polymorphic_result = true;
6578 tgl 1093 GBC 3 : have_anyelement_result = true;
1094 : }
6578 tgl 1095 ECB : else
1096 : {
1121 tgl 1097 CBC 718 : if (!OidIsValid(poly_actuals.anyelement_type))
6578 tgl 1098 ECB : {
1121 tgl 1099 CBC 434 : poly_actuals.anyelement_type =
1121 tgl 1100 GIC 434 : get_call_expr_argtype(call_expr, inargno);
1121 tgl 1101 CBC 434 : if (!OidIsValid(poly_actuals.anyelement_type))
6578 tgl 1102 LBC 0 : return false;
1103 : }
1121 tgl 1104 GIC 718 : argtypes[i] = poly_actuals.anyelement_type;
1105 : }
6578 tgl 1106 CBC 721 : break;
6578 tgl 1107 GIC 108 : case ANYARRAYOID:
5378 tgl 1108 CBC 108 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
1121 tgl 1109 ECB : {
1121 tgl 1110 CBC 9 : have_polymorphic_result = true;
6578 tgl 1111 GBC 9 : have_anyarray_result = true;
1112 : }
6578 tgl 1113 ECB : else
1114 : {
1121 tgl 1115 CBC 99 : if (!OidIsValid(poly_actuals.anyarray_type))
6578 tgl 1116 ECB : {
1121 tgl 1117 CBC 99 : poly_actuals.anyarray_type =
1121 tgl 1118 GIC 99 : get_call_expr_argtype(call_expr, inargno);
1121 tgl 1119 GBC 99 : if (!OidIsValid(poly_actuals.anyarray_type))
6578 tgl 1120 UBC 0 : return false;
1121 : }
1121 tgl 1122 GIC 99 : argtypes[i] = poly_actuals.anyarray_type;
1123 : }
6578 tgl 1124 CBC 108 : break;
4175 heikki.linnakangas 1125 GIC 12 : case ANYRANGEOID:
4175 heikki.linnakangas 1126 CBC 12 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
1121 tgl 1127 ECB : {
1121 tgl 1128 LBC 0 : have_polymorphic_result = true;
4175 heikki.linnakangas 1129 UBC 0 : have_anyrange_result = true;
1130 : }
4175 heikki.linnakangas 1131 ECB : else
1132 : {
1121 tgl 1133 CBC 12 : if (!OidIsValid(poly_actuals.anyrange_type))
4175 heikki.linnakangas 1134 EUB : {
1121 tgl 1135 GBC 12 : poly_actuals.anyrange_type =
1121 tgl 1136 GIC 12 : get_call_expr_argtype(call_expr, inargno);
1121 tgl 1137 GBC 12 : if (!OidIsValid(poly_actuals.anyrange_type))
4175 heikki.linnakangas 1138 UBC 0 : return false;
1139 : }
1121 tgl 1140 GIC 12 : argtypes[i] = poly_actuals.anyrange_type;
1141 : }
4175 heikki.linnakangas 1142 GBC 12 : break;
840 akorotkov 1143 UIC 0 : case ANYMULTIRANGEOID:
840 akorotkov 1144 UBC 0 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
840 akorotkov 1145 EUB : {
840 akorotkov 1146 UBC 0 : have_polymorphic_result = true;
1147 0 : have_anymultirange_result = true;
1148 : }
840 akorotkov 1149 EUB : else
1150 : {
840 akorotkov 1151 UBC 0 : if (!OidIsValid(poly_actuals.anymultirange_type))
840 akorotkov 1152 ECB : {
840 akorotkov 1153 UIC 0 : poly_actuals.anymultirange_type =
840 akorotkov 1154 LBC 0 : get_call_expr_argtype(call_expr, inargno);
840 akorotkov 1155 UIC 0 : if (!OidIsValid(poly_actuals.anymultirange_type))
840 akorotkov 1156 LBC 0 : return false;
840 akorotkov 1157 ECB : }
840 akorotkov 1158 UIC 0 : argtypes[i] = poly_actuals.anymultirange_type;
1159 : }
1160 0 : break;
1116 tgl 1161 CBC 69 : case ANYCOMPATIBLEOID:
1162 : case ANYCOMPATIBLENONARRAYOID:
1163 69 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
1116 tgl 1164 ECB : {
1116 tgl 1165 CBC 3 : have_polymorphic_result = true;
1116 tgl 1166 GBC 3 : have_anycompatible_result = true;
1167 : }
1116 tgl 1168 ECB : else
1169 : {
1116 tgl 1170 CBC 66 : if (!OidIsValid(anyc_actuals.anyelement_type))
1116 tgl 1171 ECB : {
1116 tgl 1172 CBC 33 : anyc_actuals.anyelement_type =
1116 tgl 1173 GIC 33 : get_call_expr_argtype(call_expr, inargno);
1116 tgl 1174 CBC 33 : if (!OidIsValid(anyc_actuals.anyelement_type))
1116 tgl 1175 LBC 0 : return false;
1176 : }
1116 tgl 1177 GIC 66 : argtypes[i] = anyc_actuals.anyelement_type;
1178 : }
1116 tgl 1179 CBC 69 : break;
1116 tgl 1180 GIC 18 : case ANYCOMPATIBLEARRAYOID:
1116 tgl 1181 CBC 18 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
1116 tgl 1182 ECB : {
1116 tgl 1183 CBC 9 : have_polymorphic_result = true;
1116 tgl 1184 GBC 9 : have_anycompatible_array_result = true;
1185 : }
1116 tgl 1186 ECB : else
1187 : {
1116 tgl 1188 CBC 9 : if (!OidIsValid(anyc_actuals.anyarray_type))
1116 tgl 1189 ECB : {
1116 tgl 1190 CBC 9 : anyc_actuals.anyarray_type =
1116 tgl 1191 GIC 9 : get_call_expr_argtype(call_expr, inargno);
1116 tgl 1192 GBC 9 : if (!OidIsValid(anyc_actuals.anyarray_type))
1116 tgl 1193 UBC 0 : return false;
1194 : }
1116 tgl 1195 GIC 9 : argtypes[i] = anyc_actuals.anyarray_type;
1196 : }
1116 tgl 1197 CBC 18 : break;
1116 tgl 1198 GIC 27 : case ANYCOMPATIBLERANGEOID:
1116 tgl 1199 CBC 27 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
1116 tgl 1200 ECB : {
1116 tgl 1201 LBC 0 : have_polymorphic_result = true;
1116 tgl 1202 UBC 0 : have_anycompatible_range_result = true;
1203 : }
1116 tgl 1204 ECB : else
1205 : {
1116 tgl 1206 CBC 27 : if (!OidIsValid(anyc_actuals.anyrange_type))
1116 tgl 1207 EUB : {
1116 tgl 1208 GBC 27 : anyc_actuals.anyrange_type =
1116 tgl 1209 GIC 27 : get_call_expr_argtype(call_expr, inargno);
1116 tgl 1210 GBC 27 : if (!OidIsValid(anyc_actuals.anyrange_type))
1116 tgl 1211 UBC 0 : return false;
1212 : }
1116 tgl 1213 GIC 27 : argtypes[i] = anyc_actuals.anyrange_type;
1214 : }
1116 tgl 1215 GBC 27 : break;
840 akorotkov 1216 UIC 0 : case ANYCOMPATIBLEMULTIRANGEOID:
840 akorotkov 1217 UBC 0 : if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
840 akorotkov 1218 EUB : {
840 akorotkov 1219 UBC 0 : have_polymorphic_result = true;
1220 0 : have_anycompatible_multirange_result = true;
1221 : }
840 akorotkov 1222 EUB : else
1223 : {
840 akorotkov 1224 UBC 0 : if (!OidIsValid(anyc_actuals.anymultirange_type))
840 akorotkov 1225 ECB : {
840 akorotkov 1226 LBC 0 : anyc_actuals.anymultirange_type =
840 akorotkov 1227 UIC 0 : get_call_expr_argtype(call_expr, inargno);
840 akorotkov 1228 LBC 0 : if (!OidIsValid(anyc_actuals.anymultirange_type))
1229 0 : return false;
1230 : }
840 akorotkov 1231 UIC 0 : argtypes[i] = anyc_actuals.anymultirange_type;
1232 : }
840 akorotkov 1233 LBC 0 : break;
6578 tgl 1234 CBC 7714 : default:
6578 tgl 1235 GIC 7714 : break;
1236 : }
5378 tgl 1237 CBC 8669 : if (argmode != PROARGMODE_OUT && argmode != PROARGMODE_TABLE)
6578 tgl 1238 GBC 8609 : inargno++;
1239 : }
6578 tgl 1240 ECB :
1241 : /* Done? */
1121 tgl 1242 GIC 6113 : if (!have_polymorphic_result)
6578 tgl 1243 CBC 6101 : return true;
6578 tgl 1244 EUB :
1245 : /* If needed, deduce one polymorphic type from others */
1121 tgl 1246 CBC 12 : if (have_anyelement_result && !OidIsValid(poly_actuals.anyelement_type))
1121 tgl 1247 UBC 0 : resolve_anyelement_from_others(&poly_actuals);
1248 :
1121 tgl 1249 CBC 12 : if (have_anyarray_result && !OidIsValid(poly_actuals.anyarray_type))
1250 3 : resolve_anyarray_from_others(&poly_actuals);
1251 :
1252 12 : if (have_anyrange_result && !OidIsValid(poly_actuals.anyrange_type))
1121 tgl 1253 LBC 0 : resolve_anyrange_from_others(&poly_actuals);
1254 :
840 akorotkov 1255 CBC 12 : if (have_anymultirange_result && !OidIsValid(poly_actuals.anymultirange_type))
840 akorotkov 1256 UBC 0 : resolve_anymultirange_from_others(&poly_actuals);
1257 :
1116 tgl 1258 CBC 12 : if (have_anycompatible_result && !OidIsValid(anyc_actuals.anyelement_type))
1116 tgl 1259 GBC 3 : resolve_anyelement_from_others(&anyc_actuals);
1260 :
1116 tgl 1261 GIC 12 : if (have_anycompatible_array_result && !OidIsValid(anyc_actuals.anyarray_type))
1116 tgl 1262 CBC 9 : resolve_anyarray_from_others(&anyc_actuals);
1263 :
1264 12 : if (have_anycompatible_range_result && !OidIsValid(anyc_actuals.anyrange_type))
1116 tgl 1265 UIC 0 : resolve_anyrange_from_others(&anyc_actuals);
1116 tgl 1266 ECB :
840 akorotkov 1267 GIC 12 : if (have_anycompatible_multirange_result && !OidIsValid(anyc_actuals.anymultirange_type))
840 akorotkov 1268 UIC 0 : resolve_anymultirange_from_others(&anyc_actuals);
840 akorotkov 1269 ECB :
6578 tgl 1270 : /* And finally replace the output column types as needed */
6578 tgl 1271 CBC 66 : for (i = 0; i < numargs; i++)
6578 tgl 1272 ECB : {
6578 tgl 1273 CBC 54 : switch (argtypes[i])
6578 tgl 1274 EUB : {
6578 tgl 1275 GBC 3 : case ANYELEMENTOID:
5786 tgl 1276 EUB : case ANYNONARRAYOID:
5851 1277 : case ANYENUMOID:
1121 tgl 1278 GBC 3 : argtypes[i] = poly_actuals.anyelement_type;
6578 1279 3 : break;
6578 tgl 1280 CBC 9 : case ANYARRAYOID:
1121 tgl 1281 GIC 9 : argtypes[i] = poly_actuals.anyarray_type;
6578 tgl 1282 CBC 9 : break;
4175 heikki.linnakangas 1283 LBC 0 : case ANYRANGEOID:
1121 tgl 1284 0 : argtypes[i] = poly_actuals.anyrange_type;
4175 heikki.linnakangas 1285 0 : break;
840 akorotkov 1286 0 : case ANYMULTIRANGEOID:
840 akorotkov 1287 UBC 0 : argtypes[i] = poly_actuals.anymultirange_type;
1288 0 : break;
1116 tgl 1289 GBC 3 : case ANYCOMPATIBLEOID:
1116 tgl 1290 EUB : case ANYCOMPATIBLENONARRAYOID:
1116 tgl 1291 GBC 3 : argtypes[i] = anyc_actuals.anyelement_type;
1292 3 : break;
1116 tgl 1293 CBC 9 : case ANYCOMPATIBLEARRAYOID:
1294 9 : argtypes[i] = anyc_actuals.anyarray_type;
1116 tgl 1295 GIC 9 : break;
1116 tgl 1296 UIC 0 : case ANYCOMPATIBLERANGEOID:
1297 0 : argtypes[i] = anyc_actuals.anyrange_type;
1116 tgl 1298 LBC 0 : break;
840 akorotkov 1299 UIC 0 : case ANYCOMPATIBLEMULTIRANGEOID:
1300 0 : argtypes[i] = anyc_actuals.anymultirange_type;
1301 0 : break;
6578 tgl 1302 GIC 30 : default:
1303 30 : break;
1304 : }
1305 : }
1306 :
1307 12 : return true;
1308 : }
1309 :
1310 : /*
6583 tgl 1311 ECB : * get_type_func_class
1312 : * Given the type OID, obtain its TYPEFUNC classification.
1991 1313 : * Also, if it's a domain, return the base type OID.
1314 : *
6583 1315 : * This is intended to centralize a bunch of formerly ad-hoc code for
1316 : * classifying types. The categories used here are useful for deciding
1317 : * how to handle functions returning the datatype.
1318 : */
1319 : static TypeFuncClass
1991 tgl 1320 GIC 86670 : get_type_func_class(Oid typid, Oid *base_typeid)
1321 : {
1322 86670 : *base_typeid = typid;
1991 tgl 1323 ECB :
6583 tgl 1324 CBC 86670 : switch (get_typtype(typid))
6583 tgl 1325 ECB : {
5851 tgl 1326 CBC 27458 : case TYPTYPE_COMPOSITE:
6583 1327 27458 : return TYPEFUNC_COMPOSITE;
5851 tgl 1328 GIC 56587 : case TYPTYPE_BASE:
5851 tgl 1329 ECB : case TYPTYPE_ENUM:
4175 heikki.linnakangas 1330 : case TYPTYPE_RANGE:
840 akorotkov 1331 : case TYPTYPE_MULTIRANGE:
6583 tgl 1332 CBC 56587 : return TYPEFUNC_SCALAR;
1991 tgl 1333 GIC 426 : case TYPTYPE_DOMAIN:
1334 426 : *base_typeid = typid = getBaseType(typid);
1335 426 : if (get_typtype(typid) == TYPTYPE_COMPOSITE)
1336 142 : return TYPEFUNC_COMPOSITE_DOMAIN;
1337 : else /* domain base type can't be a pseudotype */
1338 284 : return TYPEFUNC_SCALAR;
5851 1339 2199 : case TYPTYPE_PSEUDO:
6583 tgl 1340 CBC 2199 : if (typid == RECORDOID)
1341 1188 : return TYPEFUNC_RECORD;
6385 bruce 1342 ECB :
1343 : /*
1344 : * We treat VOID and CSTRING as legitimate scalar datatypes,
6385 bruce 1345 EUB : * mostly for the convenience of the JDBC driver (which wants to
1346 : * be able to do "SELECT * FROM foo()" for all legitimately
1347 : * user-callable functions).
1348 : */
6583 tgl 1349 GIC 1011 : if (typid == VOIDOID || typid == CSTRINGOID)
1350 1005 : return TYPEFUNC_SCALAR;
1351 6 : return TYPEFUNC_OTHER;
1352 : }
1353 : /* shouldn't get here, probably */
6583 tgl 1354 UIC 0 : return TYPEFUNC_OTHER;
1355 : }
1356 :
1357 :
1358 : /*
1359 : * get_func_arg_info
1360 : *
1361 : * Fetch info about the argument types, names, and IN/OUT modes from the
6311 tgl 1362 ECB : * pg_proc tuple. Return value is the total number of arguments.
1363 : * Other results are palloc'd. *p_argtypes is always filled in, but
1364 : * *p_argnames and *p_argmodes will be set NULL in the default cases
1365 : * (no names, and all IN arguments, respectively).
1366 : *
1367 : * Note that this function simply fetches what is in the pg_proc tuple;
1368 : * it doesn't do any interpretation of polymorphic types.
1369 : */
1370 : int
6311 tgl 1371 GIC 14948 : get_func_arg_info(HeapTuple procTup,
1372 : Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
1373 : {
1374 14948 : Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1375 : Datum proallargtypes;
1376 : Datum proargmodes;
6311 tgl 1377 ECB : Datum proargnames;
1378 : bool isNull;
1379 : ArrayType *arr;
1380 : int numargs;
1381 : Datum *elems;
1382 : int nelems;
1383 : int i;
1384 :
1385 : /* First discover the total number of parameters and get their types */
6311 tgl 1386 GIC 14948 : proallargtypes = SysCacheGetAttr(PROCOID, procTup,
1387 : Anum_pg_proc_proallargtypes,
6311 tgl 1388 ECB : &isNull);
6311 tgl 1389 CBC 14948 : if (!isNull)
6311 tgl 1390 ECB : {
1391 : /*
1392 : * We expect the arrays to be 1-D arrays of the right types; verify
1393 : * that. For the OID and char arrays, we don't need to use
6311 tgl 1394 EUB : * deconstruct_array() since the array data is just going to look like
6311 tgl 1395 ECB : * a C array of values.
1396 : */
2118 tgl 1397 CBC 3599 : arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
6311 tgl 1398 GIC 3599 : numargs = ARR_DIMS(arr)[0];
1399 3599 : if (ARR_NDIM(arr) != 1 ||
1400 3599 : numargs < 0 ||
1401 3599 : ARR_HASNULL(arr) ||
1402 3599 : ARR_ELEMTYPE(arr) != OIDOID)
867 alvherre 1403 LBC 0 : elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
6311 tgl 1404 CBC 3599 : Assert(numargs >= procStruct->pronargs);
1405 3599 : *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
1406 3599 : memcpy(*p_argtypes, ARR_DATA_PTR(arr),
1407 : numargs * sizeof(Oid));
1408 : }
1409 : else
1410 : {
6311 tgl 1411 ECB : /* If no proallargtypes, use proargtypes */
6311 tgl 1412 GIC 11349 : numargs = procStruct->proargtypes.dim1;
1413 11349 : Assert(numargs == procStruct->pronargs);
6311 tgl 1414 CBC 11349 : *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
1415 11349 : memcpy(*p_argtypes, procStruct->proargtypes.values,
1416 : numargs * sizeof(Oid));
1417 : }
6311 tgl 1418 ECB :
1419 : /* Get argument names, if available */
6311 tgl 1420 CBC 14948 : proargnames = SysCacheGetAttr(PROCOID, procTup,
6311 tgl 1421 EUB : Anum_pg_proc_proargnames,
6311 tgl 1422 ECB : &isNull);
6311 tgl 1423 CBC 14948 : if (isNull)
1424 6474 : *p_argnames = NULL;
1425 : else
1426 : {
282 peter 1427 GNC 8474 : deconstruct_array_builtin(DatumGetArrayTypeP(proargnames), TEXTOID,
1428 : &elems, NULL, &nelems);
6311 tgl 1429 GIC 8474 : if (nelems != numargs) /* should not happen */
6311 tgl 1430 LBC 0 : elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
6311 tgl 1431 CBC 8474 : *p_argnames = (char **) palloc(sizeof(char *) * numargs);
6311 tgl 1432 GIC 49260 : for (i = 0; i < numargs; i++)
5493 1433 40786 : (*p_argnames)[i] = TextDatumGetCString(elems[i]);
6311 tgl 1434 ECB : }
1435 :
1436 : /* Get argument modes, if available */
6311 tgl 1437 CBC 14948 : proargmodes = SysCacheGetAttr(PROCOID, procTup,
6311 tgl 1438 ECB : Anum_pg_proc_proargmodes,
6311 tgl 1439 EUB : &isNull);
6311 tgl 1440 GIC 14948 : if (isNull)
6311 tgl 1441 CBC 11349 : *p_argmodes = NULL;
6311 tgl 1442 ECB : else
1443 : {
6311 tgl 1444 GIC 3599 : arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
1445 3599 : if (ARR_NDIM(arr) != 1 ||
6311 tgl 1446 CBC 3599 : ARR_DIMS(arr)[0] != numargs ||
6311 tgl 1447 GIC 3599 : ARR_HASNULL(arr) ||
1448 3599 : ARR_ELEMTYPE(arr) != CHAROID)
867 alvherre 1449 UIC 0 : elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
1450 : numargs);
6311 tgl 1451 GIC 3599 : *p_argmodes = (char *) palloc(numargs * sizeof(char));
1452 3599 : memcpy(*p_argmodes, ARR_DATA_PTR(arr),
1453 : numargs * sizeof(char));
1454 : }
1455 :
1456 14948 : return numargs;
6311 tgl 1457 ECB : }
1458 :
1459 : /*
1460 : * get_func_trftypes
1461 : *
1462 : * Returns the number of transformed types used by the function.
1463 : * If there are any, a palloc'd array of the type OIDs is returned
1464 : * into *p_trftypes.
2905 peter_e 1465 : */
1466 : int
2905 peter_e 1467 GIC 70 : get_func_trftypes(HeapTuple procTup,
2905 peter_e 1468 ECB : Oid **p_trftypes)
1469 : {
1470 : Datum protrftypes;
1471 : ArrayType *arr;
1472 : int nelems;
1473 : bool isNull;
1474 :
2905 peter_e 1475 GIC 70 : protrftypes = SysCacheGetAttr(PROCOID, procTup,
2878 bruce 1476 ECB : Anum_pg_proc_protrftypes,
1477 : &isNull);
2905 peter_e 1478 CBC 70 : if (!isNull)
2905 peter_e 1479 ECB : {
1480 : /*
1481 : * We expect the arrays to be 1-D arrays of the right types; verify
2905 peter_e 1482 EUB : * that. For the OID and char arrays, we don't need to use
2905 peter_e 1483 ECB : * deconstruct_array() since the array data is just going to look like
1484 : * a C array of values.
1485 : */
2878 bruce 1486 GIC 3 : arr = DatumGetArrayTypeP(protrftypes); /* ensure not toasted */
2905 peter_e 1487 CBC 3 : nelems = ARR_DIMS(arr)[0];
2905 peter_e 1488 GIC 3 : if (ARR_NDIM(arr) != 1 ||
1489 3 : nelems < 0 ||
2905 peter_e 1490 CBC 3 : ARR_HASNULL(arr) ||
2905 peter_e 1491 GIC 3 : ARR_ELEMTYPE(arr) != OIDOID)
867 alvherre 1492 UIC 0 : elog(ERROR, "protrftypes is not a 1-D Oid array or it contains nulls");
2905 peter_e 1493 GIC 3 : *p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
1494 3 : memcpy(*p_trftypes, ARR_DATA_PTR(arr),
1495 : nelems * sizeof(Oid));
1496 :
1497 3 : return nelems;
1498 : }
1499 : else
1500 67 : return 0;
1501 : }
1502 :
1503 : /*
4931 tgl 1504 ECB : * get_func_input_arg_names
1505 : *
1506 : * Extract the names of input arguments only, given a function's
1507 : * proargnames and proargmodes entries in Datum form.
1508 : *
1509 : * Returns the number of input arguments, which is the length of the
1510 : * palloc'd array returned to *arg_names. Entries for unnamed args
1511 : * are set to NULL. You don't get anything if proargnames is NULL.
1512 : */
1513 : int
668 tgl 1514 GIC 13431 : get_func_input_arg_names(Datum proargnames, Datum proargmodes,
1515 : char ***arg_names)
4931 tgl 1516 ECB : {
1517 : ArrayType *arr;
1518 : int numargs;
1519 : Datum *argnames;
1520 : char *argmodes;
1521 : char **inargnames;
1522 : int numinargs;
1523 : int i;
1524 :
1525 : /* Do nothing if null proargnames */
4931 tgl 1526 GIC 13431 : if (proargnames == PointerGetDatum(NULL))
4931 tgl 1527 ECB : {
4931 tgl 1528 CBC 3347 : *arg_names = NULL;
1529 3347 : return 0;
4931 tgl 1530 ECB : }
4931 tgl 1531 EUB :
4931 tgl 1532 ECB : /*
1533 : * We expect the arrays to be 1-D arrays of the right types; verify that.
1534 : * For proargmodes, we don't need to use deconstruct_array() since the
4790 bruce 1535 : * array data is just going to look like a C array of values.
4931 tgl 1536 : */
2118 tgl 1537 CBC 10084 : arr = DatumGetArrayTypeP(proargnames); /* ensure not toasted */
4931 1538 10084 : if (ARR_NDIM(arr) != 1 ||
1539 10084 : ARR_HASNULL(arr) ||
4931 tgl 1540 GBC 10084 : ARR_ELEMTYPE(arr) != TEXTOID)
867 alvherre 1541 UIC 0 : elog(ERROR, "proargnames is not a 1-D text array or it contains nulls");
282 peter 1542 GNC 10084 : deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &numargs);
4931 tgl 1543 GIC 10084 : if (proargmodes != PointerGetDatum(NULL))
4931 tgl 1544 ECB : {
4931 tgl 1545 GIC 5865 : arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
1546 5865 : if (ARR_NDIM(arr) != 1 ||
4931 tgl 1547 CBC 5865 : ARR_DIMS(arr)[0] != numargs ||
4931 tgl 1548 GIC 5865 : ARR_HASNULL(arr) ||
4931 tgl 1549 GBC 5865 : ARR_ELEMTYPE(arr) != CHAROID)
867 alvherre 1550 UBC 0 : elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
1551 : numargs);
4931 tgl 1552 GIC 5865 : argmodes = (char *) ARR_DATA_PTR(arr);
1553 : }
4931 tgl 1554 ECB : else
4931 tgl 1555 CBC 4219 : argmodes = NULL;
4931 tgl 1556 ECB :
1557 : /* zero elements probably shouldn't happen, but handle it gracefully */
4931 tgl 1558 CBC 10084 : if (numargs <= 0)
4931 tgl 1559 ECB : {
4931 tgl 1560 LBC 0 : *arg_names = NULL;
1561 0 : return 0;
1562 : }
4931 tgl 1563 ECB :
1564 : /* extract input-argument names */
4931 tgl 1565 CBC 10084 : inargnames = (char **) palloc(numargs * sizeof(char *));
1566 10084 : numinargs = 0;
4931 tgl 1567 GIC 58001 : for (i = 0; i < numargs; i++)
4931 tgl 1568 ECB : {
4931 tgl 1569 CBC 47917 : if (argmodes == NULL ||
4931 tgl 1570 GIC 36669 : argmodes[i] == PROARGMODE_IN ||
1571 22143 : argmodes[i] == PROARGMODE_INOUT ||
1572 22098 : argmodes[i] == PROARGMODE_VARIADIC)
4931 tgl 1573 ECB : {
4931 tgl 1574 CBC 28282 : char *pname = TextDatumGetCString(argnames[i]);
1575 :
4931 tgl 1576 GIC 28282 : if (pname[0] != '\0')
1577 28243 : inargnames[numinargs] = pname;
1578 : else
1579 39 : inargnames[numinargs] = NULL;
1580 28282 : numinargs++;
1581 : }
1582 : }
1583 :
1584 10084 : *arg_names = inargnames;
1585 10084 : return numinargs;
1586 : }
1587 :
4931 tgl 1588 ECB :
1589 : /*
1590 : * get_func_result_name
1591 : *
1592 : * If the function has exactly one output parameter, and that parameter
1593 : * is named, return the name (as a palloc'd string). Else return NULL.
1594 : *
1595 : * This is used to determine the default output column name for functions
1596 : * returning scalar types.
1597 : */
1598 : char *
6394 tgl 1599 GIC 8671 : get_func_result_name(Oid functionId)
1600 : {
1601 : char *result;
1602 : HeapTuple procTuple;
6394 tgl 1603 ECB : Datum proargmodes;
1604 : Datum proargnames;
1605 : ArrayType *arr;
1606 : int numargs;
1607 : char *argmodes;
1608 : Datum *argnames;
1609 : int numoutargs;
1610 : int nargnames;
1611 : int i;
1612 :
1613 : /* First fetch the function's pg_proc row */
4802 rhaas 1614 GIC 8671 : procTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
6394 tgl 1615 CBC 8671 : if (!HeapTupleIsValid(procTuple))
6394 tgl 1616 UIC 0 : elog(ERROR, "cache lookup failed for function %u", functionId);
1617 :
1618 : /* If there are no named OUT parameters, return NULL */
1838 andrew 1619 GIC 9044 : if (heap_attisnull(procTuple, Anum_pg_proc_proargmodes, NULL) ||
1620 373 : heap_attisnull(procTuple, Anum_pg_proc_proargnames, NULL))
6394 tgl 1621 8313 : result = NULL;
1622 : else
1623 : {
6394 tgl 1624 ECB : /* Get the data out of the tuple */
15 dgustafsson 1625 GNC 358 : proargmodes = SysCacheGetAttrNotNull(PROCOID, procTuple,
1626 : Anum_pg_proc_proargmodes);
1627 358 : proargnames = SysCacheGetAttrNotNull(PROCOID, procTuple,
1628 : Anum_pg_proc_proargnames);
6394 tgl 1629 ECB :
1630 : /*
1631 : * We expect the arrays to be 1-D arrays of the right types; verify
1632 : * that. For the char array, we don't need to use deconstruct_array()
6394 tgl 1633 EUB : * since the array data is just going to look like a C array of
1634 : * values.
6394 tgl 1635 ECB : */
6385 bruce 1636 CBC 358 : arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
6394 tgl 1637 GIC 358 : numargs = ARR_DIMS(arr)[0];
1638 358 : if (ARR_NDIM(arr) != 1 ||
6394 tgl 1639 CBC 358 : numargs < 0 ||
6352 1640 358 : ARR_HASNULL(arr) ||
6394 1641 358 : ARR_ELEMTYPE(arr) != CHAROID)
867 alvherre 1642 UIC 0 : elog(ERROR, "proargmodes is not a 1-D char array or it contains nulls");
6394 tgl 1643 CBC 358 : argmodes = (char *) ARR_DATA_PTR(arr);
6385 bruce 1644 358 : arr = DatumGetArrayTypeP(proargnames); /* ensure not toasted */
6394 tgl 1645 358 : if (ARR_NDIM(arr) != 1 ||
1646 358 : ARR_DIMS(arr)[0] != numargs ||
6352 tgl 1647 GIC 358 : ARR_HASNULL(arr) ||
6394 1648 358 : ARR_ELEMTYPE(arr) != TEXTOID)
867 alvherre 1649 LBC 0 : elog(ERROR, "proargnames is not a 1-D text array of length %d or it contains nulls",
1650 : numargs);
282 peter 1651 GNC 358 : deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &nargnames);
6394 tgl 1652 GBC 358 : Assert(nargnames == numargs);
1653 :
6394 tgl 1654 ECB : /* scan for output argument(s) */
6394 tgl 1655 CBC 358 : result = NULL;
6394 tgl 1656 GIC 358 : numoutargs = 0;
1657 1064 : for (i = 0; i < numargs; i++)
6394 tgl 1658 EUB : {
5380 tgl 1659 GBC 706 : if (argmodes[i] == PROARGMODE_IN ||
5380 tgl 1660 GIC 358 : argmodes[i] == PROARGMODE_VARIADIC)
6394 1661 348 : continue;
1662 358 : Assert(argmodes[i] == PROARGMODE_OUT ||
1663 : argmodes[i] == PROARGMODE_INOUT ||
5378 tgl 1664 ECB : argmodes[i] == PROARGMODE_TABLE);
6394 tgl 1665 GIC 358 : if (++numoutargs > 1)
6394 tgl 1666 ECB : {
1667 : /* multiple out args, so forget it */
6394 tgl 1668 UIC 0 : result = NULL;
1669 0 : break;
1670 : }
5493 tgl 1671 GIC 358 : result = TextDatumGetCString(argnames[i]);
6394 1672 358 : if (result == NULL || result[0] == '\0')
1673 : {
1674 : /* Parameter is not named, so forget it */
6394 tgl 1675 UIC 0 : result = NULL;
1676 0 : break;
1677 : }
1678 : }
1679 : }
6394 tgl 1680 ECB :
6394 tgl 1681 GIC 8671 : ReleaseSysCache(procTuple);
6394 tgl 1682 ECB :
6394 tgl 1683 GIC 8671 : return result;
1684 : }
1685 :
1686 :
1687 : /*
1688 : * build_function_result_tupdesc_t
6583 tgl 1689 ECB : *
1690 : * Given a pg_proc row for a function, return a tuple descriptor for the
1691 : * result rowtype, or NULL if the function does not have OUT parameters.
1692 : *
5851 1693 : * Note that this does not handle resolution of polymorphic types;
6583 1694 : * that is deliberate.
1695 : */
1696 : TupleDesc
6583 tgl 1697 GIC 308575 : build_function_result_tupdesc_t(HeapTuple procTuple)
6583 tgl 1698 ECB : {
6583 tgl 1699 GIC 308575 : Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(procTuple);
6583 tgl 1700 ECB : Datum proallargtypes;
1701 : Datum proargmodes;
1702 : Datum proargnames;
1703 : bool isnull;
1704 :
1705 : /* Return NULL if the function isn't declared to return RECORD */
6583 tgl 1706 CBC 308575 : if (procform->prorettype != RECORDOID)
6583 tgl 1707 GIC 60679 : return NULL;
6583 tgl 1708 ECB :
1709 : /* If there are no OUT parameters, return NULL */
1838 andrew 1710 GIC 494748 : if (heap_attisnull(procTuple, Anum_pg_proc_proallargtypes, NULL) ||
1711 246852 : heap_attisnull(procTuple, Anum_pg_proc_proargmodes, NULL))
6583 tgl 1712 1044 : return NULL;
1713 :
1714 : /* Get the data out of the tuple */
15 dgustafsson 1715 GNC 246852 : proallargtypes = SysCacheGetAttrNotNull(PROCOID, procTuple,
1716 : Anum_pg_proc_proallargtypes);
1717 246852 : proargmodes = SysCacheGetAttrNotNull(PROCOID, procTuple,
1718 : Anum_pg_proc_proargmodes);
6583 tgl 1719 GIC 246852 : proargnames = SysCacheGetAttr(PROCOID, procTuple,
1720 : Anum_pg_proc_proargnames,
1721 : &isnull);
6583 tgl 1722 CBC 246852 : if (isnull)
6385 bruce 1723 GIC 51 : proargnames = PointerGetDatum(NULL); /* just to be sure */
1724 :
1852 peter_e 1725 246852 : return build_function_result_tupdesc_d(procform->prokind,
1726 : proallargtypes,
1727 : proargmodes,
1728 : proargnames);
1729 : }
1730 :
1731 : /*
6583 tgl 1732 ECB : * build_function_result_tupdesc_d
1733 : *
1734 : * Build a RECORD function's tupledesc from the pg_proc proallargtypes,
1735 : * proargmodes, and proargnames arrays. This is split out for the
1736 : * convenience of ProcedureCreate, which needs to be able to compute the
1737 : * tupledesc before actually creating the function.
1738 : *
1739 : * For functions (but not for procedures), returns NULL if there are not at
1852 peter_e 1740 : * least two OUT or INOUT arguments.
6583 tgl 1741 : */
1742 : TupleDesc
1852 peter_e 1743 GIC 249616 : build_function_result_tupdesc_d(char prokind,
1744 : Datum proallargtypes,
1745 : Datum proargmodes,
1746 : Datum proargnames)
1747 : {
1748 : TupleDesc desc;
6583 tgl 1749 ECB : ArrayType *arr;
1750 : int numargs;
1751 : Oid *argtypes;
1752 : char *argmodes;
6583 tgl 1753 CBC 249616 : Datum *argnames = NULL;
6583 tgl 1754 ECB : Oid *outargtypes;
6583 tgl 1755 EUB : char **outargnames;
6583 tgl 1756 ECB : int numoutargs;
1757 : int nargnames;
1758 : int i;
1759 :
1760 : /* Can't have output args if columns are null */
6583 tgl 1761 CBC 499219 : if (proallargtypes == PointerGetDatum(NULL) ||
6583 tgl 1762 GBC 249603 : proargmodes == PointerGetDatum(NULL))
6583 tgl 1763 GIC 13 : return NULL;
6583 tgl 1764 ECB :
1765 : /*
1766 : * We expect the arrays to be 1-D arrays of the right types; verify that.
1767 : * For the OID and char arrays, we don't need to use deconstruct_array()
1768 : * since the array data is just going to look like a C array of values.
1769 : */
6583 tgl 1770 CBC 249603 : arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
1771 249603 : numargs = ARR_DIMS(arr)[0];
6583 tgl 1772 GBC 249603 : if (ARR_NDIM(arr) != 1 ||
6583 tgl 1773 GIC 249603 : numargs < 0 ||
6352 tgl 1774 CBC 249603 : ARR_HASNULL(arr) ||
6583 1775 249603 : ARR_ELEMTYPE(arr) != OIDOID)
867 alvherre 1776 UIC 0 : elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
6583 tgl 1777 GIC 249603 : argtypes = (Oid *) ARR_DATA_PTR(arr);
2118 1778 249603 : arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
6583 tgl 1779 CBC 249603 : if (ARR_NDIM(arr) != 1 ||
6583 tgl 1780 GBC 249603 : ARR_DIMS(arr)[0] != numargs ||
6352 tgl 1781 GIC 249603 : ARR_HASNULL(arr) ||
6583 1782 249603 : ARR_ELEMTYPE(arr) != CHAROID)
867 alvherre 1783 LBC 0 : elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
867 alvherre 1784 ECB : numargs);
6583 tgl 1785 CBC 249603 : argmodes = (char *) ARR_DATA_PTR(arr);
1786 249603 : if (proargnames != PointerGetDatum(NULL))
1787 : {
6583 tgl 1788 GIC 249546 : arr = DatumGetArrayTypeP(proargnames); /* ensure not toasted */
1789 249546 : if (ARR_NDIM(arr) != 1 ||
6583 tgl 1790 CBC 249546 : ARR_DIMS(arr)[0] != numargs ||
6352 1791 249546 : ARR_HASNULL(arr) ||
6583 1792 249546 : ARR_ELEMTYPE(arr) != TEXTOID)
867 alvherre 1793 LBC 0 : elog(ERROR, "proargnames is not a 1-D text array of length %d or it contains nulls",
1794 : numargs);
282 peter 1795 GNC 249546 : deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &nargnames);
6583 tgl 1796 CBC 249546 : Assert(nargnames == numargs);
6583 tgl 1797 ECB : }
1798 :
1799 : /* zero elements probably shouldn't happen, but handle it gracefully */
6583 tgl 1800 CBC 249603 : if (numargs <= 0)
6583 tgl 1801 UIC 0 : return NULL;
1802 :
6583 tgl 1803 ECB : /* extract output-argument types and names */
6583 tgl 1804 GIC 249603 : outargtypes = (Oid *) palloc(numargs * sizeof(Oid));
6583 tgl 1805 CBC 249603 : outargnames = (char **) palloc(numargs * sizeof(char *));
1806 249603 : numoutargs = 0;
6583 tgl 1807 GIC 3968484 : for (i = 0; i < numargs; i++)
1808 : {
1809 : char *pname;
1810 :
5380 1811 3718881 : if (argmodes[i] == PROARGMODE_IN ||
1812 3454226 : argmodes[i] == PROARGMODE_VARIADIC)
6583 tgl 1813 CBC 270698 : continue;
6583 tgl 1814 GBC 3448183 : Assert(argmodes[i] == PROARGMODE_OUT ||
1815 : argmodes[i] == PROARGMODE_INOUT ||
5378 tgl 1816 ECB : argmodes[i] == PROARGMODE_TABLE);
6583 tgl 1817 CBC 3448183 : outargtypes[numoutargs] = argtypes[i];
6583 tgl 1818 GIC 3448183 : if (argnames)
5493 tgl 1819 CBC 3448069 : pname = TextDatumGetCString(argnames[i]);
6583 tgl 1820 ECB : else
6583 tgl 1821 CBC 114 : pname = NULL;
6583 tgl 1822 GIC 3448183 : if (pname == NULL || pname[0] == '\0')
1823 : {
1824 : /* Parameter is not named, so gin up a column name */
3380 peter_e 1825 226 : pname = psprintf("column%d", numoutargs + 1);
6583 tgl 1826 ECB : }
6583 tgl 1827 GIC 3448183 : outargnames[numoutargs] = pname;
1828 3448183 : numoutargs++;
1829 : }
1830 :
1831 : /*
1832 : * If there is no output argument, or only one, the function does not
1833 : * return tuples.
1834 : */
1852 peter_e 1835 249603 : if (numoutargs < 2 && prokind != PROKIND_PROCEDURE)
6583 tgl 1836 UIC 0 : return NULL;
1837 :
1601 andres 1838 GIC 249603 : desc = CreateTemplateTupleDesc(numoutargs);
6583 tgl 1839 3697786 : for (i = 0; i < numoutargs; i++)
6583 tgl 1840 EUB : {
6385 bruce 1841 GIC 3448183 : TupleDescInitEntry(desc, i + 1,
6583 tgl 1842 3448183 : outargnames[i],
1843 3448183 : outargtypes[i],
1844 : -1,
1845 : 0);
1846 : }
1847 :
6583 tgl 1848 GBC 249603 : return desc;
6583 tgl 1849 EUB : }
1850 :
1851 :
1852 : /*
1853 : * RelationNameGetTupleDesc
1854 : *
1855 : * Given a (possibly qualified) relation name, build a TupleDesc.
1856 : *
1857 : * Note: while this works as advertised, it's seldom the best way to
1858 : * build a tupdesc for a function's result type. It's kept around
1859 : * only for backwards compatibility with existing user-written code.
1860 : */
1861 : TupleDesc
6583 tgl 1862 UIC 0 : RelationNameGetTupleDesc(const char *relname)
1863 : {
1864 : RangeVar *relvar;
1865 : Relation rel;
1866 : TupleDesc tupdesc;
1867 : List *relname_list;
1868 :
1869 : /* Open relation and copy the tuple description */
103 tgl 1870 UNC 0 : relname_list = stringToQualifiedNameList(relname, NULL);
6583 tgl 1871 UIC 0 : relvar = makeRangeVarFromNameList(relname_list);
1872 0 : rel = relation_openrv(relvar, AccessShareLock);
6583 tgl 1873 UBC 0 : tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
6583 tgl 1874 UIC 0 : relation_close(rel, AccessShareLock);
1875 :
6583 tgl 1876 UBC 0 : return tupdesc;
6583 tgl 1877 EUB : }
1878 :
1879 : /*
1880 : * TypeGetTupleDesc
1881 : *
1882 : * Given a type Oid, build a TupleDesc. (In most cases you should be
1883 : * using get_call_result_type or one of its siblings instead of this
1884 : * routine, so that you can handle OUT parameters, RECORD result type,
6523 1885 : * and polymorphic results.)
1886 : *
1887 : * If the type is composite, *and* a colaliases List is provided, *and*
6583 1888 : * the List is of natts length, use the aliases instead of the relation
1889 : * attnames. (NB: this usage is deprecated since it may result in
1890 : * creation of unnecessary transient record types.)
1891 : *
1892 : * If the type is a base type, a single item alias List is required.
1893 : */
1894 : TupleDesc
6583 tgl 1895 UIC 0 : TypeGetTupleDesc(Oid typeoid, List *colaliases)
6583 tgl 1896 EUB : {
1991 1897 : Oid base_typeoid;
1991 tgl 1898 UIC 0 : TypeFuncClass functypclass = get_type_func_class(typeoid, &base_typeoid);
6583 1899 0 : TupleDesc tupdesc = NULL;
1900 :
1901 : /*
1991 tgl 1902 EUB : * Build a suitable tupledesc representing the output rows. We
1903 : * intentionally do not support TYPEFUNC_COMPOSITE_DOMAIN here, as it's
1904 : * unlikely that legacy callers of this obsolete function would be
1905 : * prepared to apply domain constraints.
1906 : */
6583 tgl 1907 UBC 0 : if (functypclass == TYPEFUNC_COMPOSITE)
6583 tgl 1908 EUB : {
1909 : /* Composite data type, e.g. a table's row type */
1991 tgl 1910 UIC 0 : tupdesc = lookup_rowtype_tupdesc_copy(base_typeoid, -1);
1911 :
6583 tgl 1912 UBC 0 : if (colaliases != NIL)
6583 tgl 1913 EUB : {
6583 tgl 1914 UIC 0 : int natts = tupdesc->natts;
1915 : int varattno;
6583 tgl 1916 EUB :
1917 : /* does the list length match the number of attributes? */
6583 tgl 1918 UIC 0 : if (list_length(colaliases) != natts)
1919 0 : ereport(ERROR,
1920 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1921 : errmsg("number of aliases does not match number of columns")));
6583 tgl 1922 EUB :
1923 : /* OK, use the aliases instead */
6583 tgl 1924 UIC 0 : for (varattno = 0; varattno < natts; varattno++)
1925 : {
1926 0 : char *label = strVal(list_nth(colaliases, varattno));
2058 andres 1927 0 : Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
6583 tgl 1928 EUB :
6583 tgl 1929 UBC 0 : if (label != NULL)
2058 andres 1930 UIC 0 : namestrcpy(&(attr->attname), label);
1931 : }
1932 :
1933 : /* The tuple type is now an anonymous record type */
6583 tgl 1934 UBC 0 : tupdesc->tdtypeid = RECORDOID;
6583 tgl 1935 UIC 0 : tupdesc->tdtypmod = -1;
6583 tgl 1936 EUB : }
1937 : }
6583 tgl 1938 UIC 0 : else if (functypclass == TYPEFUNC_SCALAR)
1939 : {
1940 : /* Base data type, i.e. scalar */
1941 : char *attname;
1942 :
1943 : /* the alias list is required for base types */
6583 tgl 1944 UBC 0 : if (colaliases == NIL)
6583 tgl 1945 UIC 0 : ereport(ERROR,
1946 : (errcode(ERRCODE_DATATYPE_MISMATCH),
6583 tgl 1947 EUB : errmsg("no column alias was provided")));
1948 :
1949 : /* the alias list length must be 1 */
6583 tgl 1950 UIC 0 : if (list_length(colaliases) != 1)
1951 0 : ereport(ERROR,
1952 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1953 : errmsg("number of aliases does not match number of columns")));
6583 tgl 1954 EUB :
1955 : /* OK, get the column alias */
6583 tgl 1956 UIC 0 : attname = strVal(linitial(colaliases));
6583 tgl 1957 EUB :
1601 andres 1958 UIC 0 : tupdesc = CreateTemplateTupleDesc(1);
6583 tgl 1959 0 : TupleDescInitEntry(tupdesc,
1960 : (AttrNumber) 1,
1961 : attname,
1962 : typeoid,
1963 : -1,
1964 : 0);
1965 : }
1966 0 : else if (functypclass == TYPEFUNC_RECORD)
1967 : {
1968 : /* XXX can't support this because typmod wasn't passed in ... */
1969 0 : ereport(ERROR,
1970 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1971 : errmsg("could not determine row description for function returning record")));
1972 : }
1973 : else
1974 : {
6583 tgl 1975 ECB : /* crummy error message, but parser should have caught this */
6583 tgl 1976 UIC 0 : elog(ERROR, "function in FROM has unsupported return type");
1977 : }
1978 :
6583 tgl 1979 LBC 0 : return tupdesc;
1980 : }
1981 :
1982 : /*
1983 : * extract_variadic_args
1984 : *
1985 : * Extract a set of argument values, types and NULL markers for a given
1992 andrew 1986 ECB : * input function which makes use of a VARIADIC input whose argument list
1987 : * depends on the caller context. When doing a VARIADIC call, the caller
1988 : * has provided one argument made of an array of values, so deconstruct the
1989 : * array data before using it for the next processing. If no VARIADIC call
1990 : * is used, just fill in the status data based on all the arguments given
1991 : * by the caller.
1992 : *
1993 : * This function returns the number of arguments generated, or -1 in the
1994 : * case of "VARIADIC NULL".
1995 : */
1996 : int
1992 andrew 1997 GIC 348 : extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
1992 andrew 1998 ECB : bool convert_unknown, Datum **args, Oid **types,
1999 : bool **nulls)
2000 : {
1992 andrew 2001 CBC 348 : bool variadic = get_fn_expr_variadic(fcinfo->flinfo);
2002 : Datum *args_res;
1992 andrew 2003 ECB : bool *nulls_res;
2004 : Oid *types_res;
2005 : int nargs,
1991 tgl 2006 : i;
2007 :
1992 andrew 2008 CBC 348 : *args = NULL;
1992 andrew 2009 GIC 348 : *types = NULL;
2010 348 : *nulls = NULL;
2011 :
2012 348 : if (variadic)
1992 andrew 2013 ECB : {
2014 : ArrayType *array_in;
2015 : Oid element_type;
2016 : bool typbyval;
2017 : char typalign;
2018 : int16 typlen;
2019 :
1992 andrew 2020 CBC 90 : Assert(PG_NARGS() == variadic_start + 1);
1992 andrew 2021 ECB :
1992 andrew 2022 CBC 90 : if (PG_ARGISNULL(variadic_start))
2023 12 : return -1;
2024 :
2025 78 : array_in = PG_GETARG_ARRAYTYPE_P(variadic_start);
1992 andrew 2026 GIC 78 : element_type = ARR_ELEMTYPE(array_in);
1992 andrew 2027 ECB :
1992 andrew 2028 CBC 78 : get_typlenbyvalalign(element_type,
2029 : &typlen, &typbyval, &typalign);
1992 andrew 2030 GIC 78 : deconstruct_array(array_in, element_type, typlen, typbyval,
2031 : typalign, &args_res, &nulls_res,
2032 : &nargs);
2033 :
2034 : /* All the elements of the array have the same type */
2035 78 : types_res = (Oid *) palloc0(nargs * sizeof(Oid));
2036 318 : for (i = 0; i < nargs; i++)
2037 240 : types_res[i] = element_type;
1992 andrew 2038 ECB : }
2039 : else
2040 : {
1992 andrew 2041 GIC 258 : nargs = PG_NARGS() - variadic_start;
1991 tgl 2042 CBC 258 : Assert(nargs > 0);
1992 andrew 2043 GIC 258 : nulls_res = (bool *) palloc0(nargs * sizeof(bool));
1992 andrew 2044 CBC 258 : args_res = (Datum *) palloc0(nargs * sizeof(Datum));
2045 258 : types_res = (Oid *) palloc0(nargs * sizeof(Oid));
2046 :
2047 1002 : for (i = 0; i < nargs; i++)
1992 andrew 2048 ECB : {
1992 andrew 2049 GIC 744 : nulls_res[i] = PG_ARGISNULL(i + variadic_start);
2050 744 : types_res[i] = get_fn_expr_argtype(fcinfo->flinfo,
2051 : i + variadic_start);
2052 :
1992 andrew 2053 ECB : /*
2054 : * Turn a constant (more or less literal) value that's of unknown
2055 : * type into text if required. Unknowns come in as a cstring
1991 tgl 2056 : * pointer. Note: for functions declared as taking type "any", the
2057 : * parser will not do any type conversion on unknown-type literals
1991 tgl 2058 EUB : * (that is, undecorated strings or NULLs).
2059 : */
1992 andrew 2060 GIC 744 : if (convert_unknown &&
2061 1098 : types_res[i] == UNKNOWNOID &&
2062 354 : get_fn_expr_arg_stable(fcinfo->flinfo, i + variadic_start))
2063 : {
2064 354 : types_res[i] = TEXTOID;
2065 :
1992 andrew 2066 CBC 354 : if (PG_ARGISNULL(i + variadic_start))
2067 36 : args_res[i] = (Datum) 0;
1992 andrew 2068 ECB : else
1992 andrew 2069 GIC 318 : args_res[i] =
1992 andrew 2070 CBC 318 : CStringGetTextDatum(PG_GETARG_POINTER(i + variadic_start));
2071 : }
2072 : else
2073 : {
2074 : /* no conversion needed, just take the datum as given */
1992 andrew 2075 GIC 390 : args_res[i] = PG_GETARG_DATUM(i + variadic_start);
2076 : }
2077 :
2078 744 : if (!OidIsValid(types_res[i]) ||
2079 744 : (convert_unknown && types_res[i] == UNKNOWNOID))
1992 andrew 2080 UIC 0 : ereport(ERROR,
2081 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2082 : errmsg("could not determine data type for argument %d",
2083 : i + 1)));
2084 : }
2085 : }
2086 :
2087 : /* Fill in results */
1992 andrew 2088 GIC 336 : *args = args_res;
2089 336 : *nulls = nulls_res;
2090 336 : *types = types_res;
2091 :
2092 336 : return nargs;
2093 : }
|