280{
285 natts;
287
288 /* check for unsupported flags */
290
291 /*
292 * FunctionScan should not have any children.
293 */
296
297 /*
298 * create new ScanState for node
299 */
304 scanstate->
eflags = eflags;
305
306 /*
307 * are we adding an ordinality column?
308 */
310
311 scanstate->
nfuncs = nfuncs;
314 else
315 scanstate->
simple =
false;
316
317 /*
318 * Ordinal 0 represents the "before the first row" position.
319 *
320 * We need to track ordinal position even when not adding an ordinality
321 * column to the result, in order to handle backwards scanning properly
322 * with multiple functions with different result sizes. (We can't position
323 * any individual function's tuplestore any more than 1 place beyond its
324 * end, so when scanning backwards, we need to know when to start
325 * including the function in the scan again.)
326 */
328
329 /*
330 * Miscellaneous initialization
331 *
332 * create expression context for node
333 */
335
337
338 natts = 0;
341 {
344 int colcount = rtfunc->funccolcount;
347
352
353 /*
354 * Don't allocate the tuplestores; the actual calls to the functions
355 * do that. NULL means that we have not called the function yet (or
356 * need to call it again after a rescan).
357 */
360
361 /*
362 * Now build a tupdesc showing the result type we expect from the
363 * function. If we have a coldeflist then that takes priority (note
364 * the parser enforces that there is one if the function's nominal
365 * output type is RECORD). Otherwise use get_expr_result_type.
366 *
367 * Note that if the function returns a named composite type, that may
368 * now contain more or different columns than it did when the plan was
369 * made. For both that and the RECORD case, we need to check tuple
370 * compatibility. ExecMakeTableFunctionResult handles some of this,
371 * and CheckVarSlotCompatibility provides a backstop.
372 */
373 if (rtfunc->funccolnames !=
NIL)
374 {
376 rtfunc->funccoltypes,
377 rtfunc->funccoltypmods,
378 rtfunc->funccolcollations);
379
380 /*
381 * For RECORD results, make sure a typmod has been assigned. (The
382 * function should do this for itself, but let's cover things in
383 * case it doesn't.)
384 */
386 }
387 else
388 {
391
393 &funcrettype,
394 &tupdesc);
395
398 {
399 /* Composite data type, e.g. a table's row type */
401 /* Must copy it out of typcache for safety */
403 }
405 {
406 /* Base data type, i.e. scalar */
410 NULL, /* don't care about the name here */
411 funcrettype,
412 -1,
413 0);
417 }
418 else
419 {
420 /* crummy error message, but parser should have caught this */
421 elog(
ERROR,
"function in FROM has unsupported return type");
422 }
423 }
424
427
428 /*
429 * We only need separate slots for the function results if we are
430 * doing ordinality or multiple functions; otherwise, we'll fetch
431 * function results directly into the scan slot.
432 */
434 {
437 }
438 else
440
441 natts += colcount;
443 }
444
445 /*
446 * Create the combined TupleDesc
447 *
448 * If there is just one function without ordinality, the scan result
449 * tupdesc is the same as the function result tupdesc --- except that we
450 * may stuff new names into it below, so drop any rowtype label.
451 */
453 {
457 }
458 else
459 {
461
463 natts++;
464
466
467 for (
i = 0;
i < nfuncs;
i++)
468 {
472
473 for (
j = 1;
j <= colcount;
j++)
475 }
476
477 /* If doing ordinality, add a column of type "bigint" at the end */
479 {
481 ++attno,
482 NULL, /* don't care about the name here */
483 INT8OID,
484 -1,
485 0);
486 }
487
489 }
490
491 /*
492 * Initialize scan slot and type.
493 */
496
497 /*
498 * Initialize result slot, type and projection.
499 */
502
503 /*
504 * initialize child expressions
505 */
508
509 /*
510 * Create a memory context that ExecMakeTableFunctionResult can use to
511 * evaluate function arguments in. We can't use the per-tuple context for
512 * this because it gets reset too often; but we don't want to leak
513 * evaluation results into the query-lifespan context either. We just
514 * need one context, because we evaluate each function separately.
515 */
517 "Table function arguments",
519
520 return scanstate;
521}
ExprState * ExecInitQual(List *qual, PlanState *parent)
SetExprState * ExecInitTableFunctionResult(Expr *expr, ExprContext *econtext, PlanState *parent)
void ExecAssignScanProjectionInfo(ScanState *node)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTypeTL(PlanState *planstate)
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsMinimalTuple
void ExecAssignExprContext(EState *estate, PlanState *planstate)
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
@ TYPEFUNC_COMPOSITE_DOMAIN
Assert(PointerIsAligned(start, uint64))
MemoryContext CurrentMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
Oid exprCollation(const Node *expr)
static TupleTableSlot * ExecFunctionScan(PlanState *pstate)
static int list_length(const List *l)
TupleTableSlot * func_slot
ExprContext * ps_ExprContext
ExecProcNodeMtd ExecProcNode
TupleDesc CreateTemplateTupleDesc(int natts)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)