PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
functions.h File Reference
#include "nodes/execnodes.h"
#include "tcop/dest.h"
Include dependency graph for functions.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SQLFunctionParseInfo
 

Typedefs

typedef struct SQLFunctionParseInfo SQLFunctionParseInfo
 
typedef SQLFunctionParseInfoSQLFunctionParseInfoPtr
 

Functions

Datum fmgr_sql (PG_FUNCTION_ARGS)
 
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info (HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
 
void sql_fn_parser_setup (struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
 
void check_sql_fn_statements (List *queryTreeLists)
 
bool check_sql_fn_retval (List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
 
DestReceiverCreateSQLFunctionDestReceiver (void)
 

Typedef Documentation

◆ SQLFunctionParseInfo

◆ SQLFunctionParseInfoPtr

Definition at line 35 of file functions.h.

Function Documentation

◆ check_sql_fn_retval()

bool check_sql_fn_retval ( List queryTreeLists,
Oid  rettype,
TupleDesc  rettupdesc,
char  prokind,
bool  insertDroppedCols 
)

Definition at line 2021 of file functions.c.

2025{
2026 List *queryTreeList;
2027
2028 /*
2029 * We consider only the last sublist of Query nodes, so that only the last
2030 * original statement is a candidate to produce the result. This is a
2031 * change from pre-v18 versions, which would back up to the last statement
2032 * that includes a canSetTag query, thus ignoring any ending statement(s)
2033 * that rewrite to DO INSTEAD NOTHING. That behavior was undocumented and
2034 * there seems no good reason for it, except that it was an artifact of
2035 * the original coding.
2036 *
2037 * If the function body is completely empty, handle that the same as if
2038 * the last query had rewritten to nothing.
2039 */
2040 if (queryTreeLists != NIL)
2041 queryTreeList = llast_node(List, queryTreeLists);
2042 else
2043 queryTreeList = NIL;
2044
2045 return check_sql_stmt_retval(queryTreeList,
2046 rettype, rettupdesc,
2047 prokind, insertDroppedCols);
2048}
static bool check_sql_stmt_retval(List *queryTreeList, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
Definition: functions.c:2055
#define NIL
Definition: pg_list.h:68
#define llast_node(type, l)
Definition: pg_list.h:202
Definition: pg_list.h:54

References check_sql_stmt_retval(), llast_node, and NIL.

Referenced by fmgr_sql_validator(), inline_function(), and inline_set_returning_function().

◆ check_sql_fn_statements()

void check_sql_fn_statements ( List queryTreeLists)

Definition at line 1940 of file functions.c.

1941{
1942 ListCell *lc;
1943
1944 /* We are given a list of sublists of Queries */
1945 foreach(lc, queryTreeLists)
1946 {
1947 List *sublist = lfirst_node(List, lc);
1948
1949 check_sql_fn_statement(sublist);
1950 }
1951}
static void check_sql_fn_statement(List *queryTreeList)
Definition: functions.c:1957
#define lfirst_node(type, lc)
Definition: pg_list.h:176

References check_sql_fn_statement(), and lfirst_node.

Referenced by fmgr_sql_validator().

◆ CreateSQLFunctionDestReceiver()

DestReceiver * CreateSQLFunctionDestReceiver ( void  )

Definition at line 2522 of file functions.c.

2523{
2525
2530 self->pub.mydest = DestSQLFunction;
2531
2532 /* private fields will be set by postquel_start */
2533
2534 return (DestReceiver *) self;
2535}
@ DestSQLFunction
Definition: dest.h:96
static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: functions.c:2541
static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: functions.c:2550
static void sqlfunction_destroy(DestReceiver *self)
Definition: functions.c:2576
static void sqlfunction_shutdown(DestReceiver *self)
Definition: functions.c:2567
void * palloc0(Size size)
Definition: mcxt.c:1970
DestReceiver pub
Definition: functions.c:46
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
CommandDest mydest
Definition: dest.h:128

References DestSQLFunction, _DestReceiver::mydest, palloc0(), DR_sqlfunction::pub, _DestReceiver::rDestroy, _DestReceiver::receiveSlot, _DestReceiver::rShutdown, _DestReceiver::rStartup, sqlfunction_destroy(), sqlfunction_receive(), sqlfunction_shutdown(), and sqlfunction_startup().

Referenced by CreateDestReceiver().

◆ fmgr_sql()

Datum fmgr_sql ( PG_FUNCTION_ARGS  )

Definition at line 1444 of file functions.c.

1445{
1446 SQLFunctionCachePtr fcache;
1447 SQLFunctionLink *flink;
1448 ErrorContextCallback sqlerrcontext;
1449 MemoryContext tscontext;
1450 MemoryContext oldcontext;
1451 bool randomAccess;
1452 bool lazyEvalOK;
1453 bool pushed_snapshot;
1454 execution_state *es;
1455 TupleTableSlot *slot;
1456 Datum result;
1457
1458 /* Check call context */
1459 if (fcinfo->flinfo->fn_retset)
1460 {
1461 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1462
1463 /*
1464 * For simplicity, we require callers to support both set eval modes.
1465 * There are cases where we must use one or must use the other, and
1466 * it's not really worthwhile to postpone the check till we know. But
1467 * note we do not require caller to provide an expectedDesc.
1468 */
1469 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1470 (rsi->allowedModes & SFRM_ValuePerCall) == 0 ||
1471 (rsi->allowedModes & SFRM_Materialize) == 0)
1472 ereport(ERROR,
1473 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1474 errmsg("set-valued function called in context that cannot accept a set")));
1475 randomAccess = rsi->allowedModes & SFRM_Materialize_Random;
1476 lazyEvalOK = !(rsi->allowedModes & SFRM_Materialize_Preferred);
1477 /* tuplestore must have query lifespan */
1478 tscontext = rsi->econtext->ecxt_per_query_memory;
1479 }
1480 else
1481 {
1482 randomAccess = false;
1483 lazyEvalOK = true;
1484 /* tuplestore needn't outlive caller context */
1485 tscontext = CurrentMemoryContext;
1486 }
1487
1488 /*
1489 * Initialize fcache if starting a fresh execution.
1490 */
1491 fcache = init_sql_fcache(fcinfo, lazyEvalOK);
1492 /* init_sql_fcache also ensures we have a SQLFunctionLink */
1493 flink = fcinfo->flinfo->fn_extra;
1494
1495 /*
1496 * Now we can set up error traceback support for ereport()
1497 */
1498 sqlerrcontext.callback = sql_exec_error_callback;
1499 sqlerrcontext.arg = fcache;
1500 sqlerrcontext.previous = error_context_stack;
1501 error_context_stack = &sqlerrcontext;
1502
1503 /*
1504 * Build tuplestore to hold results, if we don't have one already. Make
1505 * sure it's in a suitable context.
1506 */
1507 oldcontext = MemoryContextSwitchTo(tscontext);
1508
1509 if (!fcache->tstore)
1510 fcache->tstore = tuplestore_begin_heap(randomAccess, false, work_mem);
1511
1512 /*
1513 * Switch to context in which the fcache lives. The sub-executor is
1514 * responsible for deleting per-tuple information. (XXX in the case of a
1515 * long-lived FmgrInfo, this policy potentially causes memory leakage, but
1516 * it's not very clear where we could keep stuff instead. Fortunately,
1517 * there are few if any cases where set-returning functions are invoked
1518 * via FmgrInfos that would outlive the calling query.)
1519 */
1521
1522 /*
1523 * Find first unfinished execution_state. If none, advance to the next
1524 * query in function.
1525 */
1526 do
1527 {
1528 es = fcache->eslist;
1529 while (es && es->status == F_EXEC_DONE)
1530 es = es->next;
1531 if (es)
1532 break;
1533 } while (init_execution_state(fcache));
1534
1535 /*
1536 * Execute each command in the function one after another until we either
1537 * run out of commands or get a result row from a lazily-evaluated SELECT.
1538 *
1539 * Notes about snapshot management:
1540 *
1541 * In a read-only function, we just use the surrounding query's snapshot.
1542 *
1543 * In a non-read-only function, we rely on the fact that we'll never
1544 * suspend execution between queries of the function: the only reason to
1545 * suspend execution before completion is if we are returning a row from a
1546 * lazily-evaluated SELECT. So, when first entering this loop, we'll
1547 * either start a new query (and push a fresh snapshot) or re-establish
1548 * the active snapshot from the existing query descriptor. If we need to
1549 * start a new query in a subsequent execution of the loop, either we need
1550 * a fresh snapshot (and pushed_snapshot is false) or the existing
1551 * snapshot is on the active stack and we can just bump its command ID.
1552 */
1553 pushed_snapshot = false;
1554 while (es)
1555 {
1556 bool completed;
1557
1558 if (es->status == F_EXEC_START)
1559 {
1560 /*
1561 * If not read-only, be sure to advance the command counter for
1562 * each command, so that all work to date in this transaction is
1563 * visible. Take a new snapshot if we don't have one yet,
1564 * otherwise just bump the command ID in the existing snapshot.
1565 */
1566 if (!fcache->func->readonly_func)
1567 {
1569 if (!pushed_snapshot)
1570 {
1572 pushed_snapshot = true;
1573 }
1574 else
1576 }
1577
1578 postquel_start(es, fcache);
1579 }
1580 else if (!fcache->func->readonly_func && !pushed_snapshot)
1581 {
1582 /* Re-establish active snapshot when re-entering function */
1584 pushed_snapshot = true;
1585 }
1586
1587 completed = postquel_getnext(es, fcache);
1588
1589 /*
1590 * If we ran the command to completion, we can shut it down now. Any
1591 * row(s) we need to return are safely stashed in the tuplestore, and
1592 * we want to be sure that, for example, AFTER triggers get fired
1593 * before we return anything. Also, if the function doesn't return
1594 * set, we can shut it down anyway because it must be a SELECT and we
1595 * don't care about fetching any more result rows.
1596 */
1597 if (completed || !fcache->func->returnsSet)
1598 postquel_end(es);
1599
1600 /*
1601 * Break from loop if we didn't shut down (implying we got a
1602 * lazily-evaluated row). Otherwise we'll press on till the whole
1603 * function is done, relying on the tuplestore to keep hold of the
1604 * data to eventually be returned. This is necessary since an
1605 * INSERT/UPDATE/DELETE RETURNING that sets the result might be
1606 * followed by additional rule-inserted commands, and we want to
1607 * finish doing all those commands before we return anything.
1608 */
1609 if (es->status != F_EXEC_DONE)
1610 break;
1611
1612 /*
1613 * Advance to next execution_state, and perhaps next query.
1614 */
1615 es = es->next;
1616 while (!es)
1617 {
1618 /*
1619 * Flush the current snapshot so that we will take a new one for
1620 * the new query list. This ensures that new snaps are taken at
1621 * original-query boundaries, matching the behavior of interactive
1622 * execution.
1623 */
1624 if (pushed_snapshot)
1625 {
1627 pushed_snapshot = false;
1628 }
1629
1630 if (!init_execution_state(fcache))
1631 break; /* end of function */
1632
1633 es = fcache->eslist;
1634 }
1635 }
1636
1637 /*
1638 * The tuplestore now contains whatever row(s) we are supposed to return.
1639 */
1640 if (fcache->func->returnsSet)
1641 {
1642 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1643
1644 if (es)
1645 {
1646 /*
1647 * If we stopped short of being done, we must have a lazy-eval
1648 * row.
1649 */
1650 Assert(es->lazyEval);
1651 /* Re-use the junkfilter's output slot to fetch back the tuple */
1652 Assert(fcache->junkFilter);
1653 slot = fcache->junkFilter->jf_resultSlot;
1654 if (!tuplestore_gettupleslot(fcache->tstore, true, false, slot))
1655 elog(ERROR, "failed to fetch lazy-eval tuple");
1656 /* Extract the result as a datum, and copy out from the slot */
1657 result = postquel_get_single_result(slot, fcinfo,
1658 fcache, oldcontext);
1659 /* Clear the tuplestore, but keep it for next time */
1660 /* NB: this might delete the slot's content, but we don't care */
1661 tuplestore_clear(fcache->tstore);
1662
1663 /*
1664 * Let caller know we're not finished.
1665 */
1667
1668 /*
1669 * Ensure we will get shut down cleanly if the exprcontext is not
1670 * run to completion.
1671 */
1672 if (!fcache->shutdown_reg)
1673 {
1676 PointerGetDatum(flink));
1677 fcache->shutdown_reg = true;
1678 }
1679 }
1680 else if (fcache->lazyEval)
1681 {
1682 /*
1683 * We are done with a lazy evaluation. Clean up.
1684 */
1685 tuplestore_clear(fcache->tstore);
1686
1687 /*
1688 * Let caller know we're finished.
1689 */
1690 rsi->isDone = ExprEndResult;
1691
1692 fcinfo->isnull = true;
1693 result = (Datum) 0;
1694
1695 /* Deregister shutdown callback, if we made one */
1696 if (fcache->shutdown_reg)
1697 {
1700 PointerGetDatum(flink));
1701 fcache->shutdown_reg = false;
1702 }
1703 }
1704 else
1705 {
1706 /*
1707 * We are done with a non-lazy evaluation. Return whatever is in
1708 * the tuplestore. (It is now caller's responsibility to free the
1709 * tuplestore when done.)
1710 */
1712 rsi->setResult = fcache->tstore;
1713 fcache->tstore = NULL;
1714 /* must copy desc because execSRF.c will free it */
1715 if (fcache->junkFilter)
1716 {
1717 /* setDesc must be allocated in suitable context */
1718 MemoryContextSwitchTo(tscontext);
1721 }
1722
1723 fcinfo->isnull = true;
1724 result = (Datum) 0;
1725
1726 /* Deregister shutdown callback, if we made one */
1727 if (fcache->shutdown_reg)
1728 {
1731 PointerGetDatum(flink));
1732 fcache->shutdown_reg = false;
1733 }
1734 }
1735 }
1736 else
1737 {
1738 /*
1739 * Non-set function. If we got a row, return it; else return NULL.
1740 */
1741 if (fcache->junkFilter)
1742 {
1743 /* Re-use the junkfilter's output slot to fetch back the tuple */
1744 slot = fcache->junkFilter->jf_resultSlot;
1745 if (tuplestore_gettupleslot(fcache->tstore, true, false, slot))
1746 result = postquel_get_single_result(slot, fcinfo,
1747 fcache, oldcontext);
1748 else
1749 {
1750 fcinfo->isnull = true;
1751 result = (Datum) 0;
1752 }
1753 }
1754 else
1755 {
1756 /* Should only get here for VOID functions and procedures */
1757 Assert(fcache->func->rettype == VOIDOID);
1758 fcinfo->isnull = true;
1759 result = (Datum) 0;
1760 }
1761
1762 /* Clear the tuplestore, but keep it for next time */
1763 tuplestore_clear(fcache->tstore);
1764 }
1765
1766 /* Pop snapshot if we have pushed one */
1767 if (pushed_snapshot)
1769
1770 MemoryContextSwitchTo(oldcontext);
1771
1772 /*
1773 * If we've gone through every command in the function, we are done.
1774 * Release the cache to start over again on next call.
1775 */
1776 if (es == NULL)
1777 {
1778 if (fcache->tstore)
1779 tuplestore_end(fcache->tstore);
1780 Assert(fcache->cplan == NULL);
1781 flink->fcache = NULL;
1783 }
1784
1785 error_context_stack = sqlerrcontext.previous;
1786
1787 return result;
1788}
ErrorContextCallback * error_context_stack
Definition: elog.c:95
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:149
void UnregisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition: execUtils.c:990
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition: execUtils.c:964
@ ExprMultipleResult
Definition: execnodes.h:323
@ ExprEndResult
Definition: execnodes.h:324
@ SFRM_Materialize_Preferred
Definition: execnodes.h:338
@ SFRM_ValuePerCall
Definition: execnodes.h:335
@ SFRM_Materialize_Random
Definition: execnodes.h:337
@ SFRM_Materialize
Definition: execnodes.h:336
static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
Definition: functions.c:1290
static void postquel_end(execution_state *es)
Definition: functions.c:1325
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
Definition: functions.c:1226
static bool init_execution_state(SQLFunctionCachePtr fcache)
Definition: functions.c:657
static Datum postquel_get_single_result(TupleTableSlot *slot, FunctionCallInfo fcinfo, SQLFunctionCachePtr fcache, MemoryContext resultcontext)
Definition: functions.c:1401
static void sql_exec_error_callback(void *arg)
Definition: functions.c:1829
static void ShutdownSQLFunction(Datum arg)
Definition: functions.c:1867
@ F_EXEC_START
Definition: functions.c:63
@ F_EXEC_DONE
Definition: functions.c:63
static SQLFunctionCache * init_sql_fcache(FunctionCallInfo fcinfo, bool lazyEvalOK)
Definition: functions.c:537
int work_mem
Definition: globals.c:132
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:271
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:669
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:731
void PopActiveSnapshot(void)
Definition: snapmgr.c:762
struct ErrorContextCallback * previous
Definition: elog.h:297
void(* callback)(void *arg)
Definition: elog.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:275
TupleDesc jf_cleanTupType
Definition: execnodes.h:414
TupleTableSlot * jf_resultSlot
Definition: execnodes.h:416
Snapshot snapshot
Definition: execdesc.h:40
SetFunctionReturnMode returnMode
Definition: execnodes.h:355
ExprContext * econtext
Definition: execnodes.h:351
TupleDesc setDesc
Definition: execnodes.h:359
Tuplestorestate * setResult
Definition: execnodes.h:358
int allowedModes
Definition: execnodes.h:353
ExprDoneCond isDone
Definition: execnodes.h:356
MemoryContext fcontext
Definition: functions.c:175
execution_state * eslist
Definition: functions.c:169
SQLFunctionHashEntry * func
Definition: functions.c:148
CachedPlan * cplan
Definition: functions.c:167
JunkFilter * junkFilter
Definition: functions.c:158
Tuplestorestate * tstore
Definition: functions.c:156
ExecStatus status
Definition: functions.c:69
struct execution_state * next
Definition: functions.c:68
QueryDesc * qd
Definition: functions.c:73
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:245
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1130
void tuplestore_clear(Tuplestorestate *state)
Definition: tuplestore.c:430
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:330
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:492
void CommandCounterIncrement(void)
Definition: xact.c:1100

References ReturnSetInfo::allowedModes, ErrorContextCallback::arg, Assert(), ErrorContextCallback::callback, CommandCounterIncrement(), SQLFunctionCache::cplan, CreateTupleDescCopy(), CurrentMemoryContext, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elog, ereport, errcode(), errmsg(), ERROR, error_context_stack, SQLFunctionCache::eslist, ExprEndResult, ExprMultipleResult, F_EXEC_DONE, F_EXEC_START, SQLFunctionLink::fcache, SQLFunctionCache::fcontext, SQLFunctionCache::func, GetTransactionSnapshot(), if(), init_execution_state(), init_sql_fcache(), IsA, ReturnSetInfo::isDone, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, SQLFunctionCache::junkFilter, execution_state::lazyEval, SQLFunctionCache::lazyEval, MemoryContextDelete(), MemoryContextSwitchTo(), execution_state::next, PointerGetDatum(), PopActiveSnapshot(), postquel_end(), postquel_get_single_result(), postquel_getnext(), postquel_start(), ErrorContextCallback::previous, PushActiveSnapshot(), execution_state::qd, SQLFunctionHashEntry::readonly_func, RegisterExprContextCallback(), SQLFunctionHashEntry::rettype, ReturnSetInfo::returnMode, SQLFunctionHashEntry::returnsSet, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Preferred, SFRM_Materialize_Random, SFRM_ValuePerCall, SQLFunctionCache::shutdown_reg, ShutdownSQLFunction(), QueryDesc::snapshot, sql_exec_error_callback(), execution_state::status, SQLFunctionCache::tstore, tuplestore_begin_heap(), tuplestore_clear(), tuplestore_end(), tuplestore_gettupleslot(), UnregisterExprContextCallback(), UpdateActiveSnapshotCommandId(), and work_mem.

Referenced by fmgr_info_cxt_security().

◆ prepare_sql_fn_parse_info()

SQLFunctionParseInfoPtr prepare_sql_fn_parse_info ( HeapTuple  procedureTuple,
Node call_expr,
Oid  inputCollation 
)

Definition at line 252 of file functions.c.

255{
257 Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
258 int nargs;
259
261
262 /* Function's name (only) can be used to qualify argument names */
263 pinfo->fname = pstrdup(NameStr(procedureStruct->proname));
264
265 /* Save the function's input collation */
266 pinfo->collation = inputCollation;
267
268 /*
269 * Copy input argument types from the pg_proc entry, then resolve any
270 * polymorphic types.
271 */
272 pinfo->nargs = nargs = procedureStruct->pronargs;
273 if (nargs > 0)
274 {
275 Oid *argOidVect;
276 int argnum;
277
278 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
279 memcpy(argOidVect,
280 procedureStruct->proargtypes.values,
281 nargs * sizeof(Oid));
282
283 for (argnum = 0; argnum < nargs; argnum++)
284 {
285 Oid argtype = argOidVect[argnum];
286
287 if (IsPolymorphicType(argtype))
288 {
289 argtype = get_call_expr_argtype(call_expr, argnum);
290 if (argtype == InvalidOid)
292 (errcode(ERRCODE_DATATYPE_MISMATCH),
293 errmsg("could not determine actual type of argument declared %s",
294 format_type_be(argOidVect[argnum]))));
295 argOidVect[argnum] = argtype;
296 }
297 }
298
299 pinfo->argtypes = argOidVect;
300 }
301
302 /*
303 * Collect names of arguments, too, if any
304 */
305 if (nargs > 0)
306 {
307 Datum proargnames;
308 Datum proargmodes;
309 int n_arg_names;
310 bool isNull;
311
312 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
313 Anum_pg_proc_proargnames,
314 &isNull);
315 if (isNull)
316 proargnames = PointerGetDatum(NULL); /* just to be sure */
317
318 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
319 Anum_pg_proc_proargmodes,
320 &isNull);
321 if (isNull)
322 proargmodes = PointerGetDatum(NULL); /* just to be sure */
323
324 n_arg_names = get_func_input_arg_names(proargnames, proargmodes,
325 &pinfo->argnames);
326
327 /* Paranoia: ignore the result if too few array entries */
328 if (n_arg_names < nargs)
329 pinfo->argnames = NULL;
330 }
331 else
332 pinfo->argnames = NULL;
333
334 return pinfo;
335}
#define NameStr(name)
Definition: c.h:717
Oid get_call_expr_argtype(Node *expr, int argnum)
Definition: fmgr.c:1929
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int get_func_input_arg_names(Datum proargnames, Datum proargmodes, char ***arg_names)
Definition: funcapi.c:1522
SQLFunctionParseInfo * SQLFunctionParseInfoPtr
Definition: functions.h:35
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
char * pstrdup(const char *in)
Definition: mcxt.c:2322
void * palloc(Size size)
Definition: mcxt.c:1940
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600

References SQLFunctionParseInfo::argnames, SQLFunctionParseInfo::argtypes, SQLFunctionParseInfo::collation, ereport, errcode(), errmsg(), ERROR, SQLFunctionParseInfo::fname, format_type_be(), get_call_expr_argtype(), get_func_input_arg_names(), GETSTRUCT(), InvalidOid, NameStr, SQLFunctionParseInfo::nargs, palloc(), palloc0(), PointerGetDatum(), pstrdup(), and SysCacheGetAttr().

Referenced by fmgr_sql_validator(), inline_function(), inline_set_returning_function(), and sql_compile_callback().

◆ sql_fn_parser_setup()

void sql_fn_parser_setup ( struct ParseState pstate,
SQLFunctionParseInfoPtr  pinfo 
)

Definition at line 341 of file functions.c.

342{
343 pstate->p_pre_columnref_hook = NULL;
346 /* no need to use p_coerce_param_hook */
347 pstate->p_ref_hook_state = pinfo;
348}
static Node * sql_fn_param_ref(ParseState *pstate, ParamRef *pref)
Definition: functions.c:470
static Node * sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: functions.c:354
void * p_ref_hook_state
Definition: parse_node.h:258
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:256
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:254
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:255

References ParseState::p_paramref_hook, ParseState::p_post_columnref_hook, ParseState::p_pre_columnref_hook, ParseState::p_ref_hook_state, sql_fn_param_ref(), and sql_fn_post_column_ref().

Referenced by fmgr_sql_validator(), inline_function(), inline_set_returning_function(), interpret_AS_clause(), and prepare_next_query().