138 int paramno,
int location);
140 const char *paramname,
int location);
158 bool tlist_is_modifiable,
160 bool *upper_tlist_nontrivial);
196 pinfo->
nargs = nargs = procedureStruct->pronargs;
204 procedureStruct->proargtypes.values,
205 nargs *
sizeof(
Oid));
207 for (argnum = 0; argnum < nargs; argnum++)
209 Oid argtype = argOidVect[argnum];
211 if (IsPolymorphicType(argtype))
216 (
errcode(ERRCODE_DATATYPE_MISMATCH),
217 errmsg(
"could not determine actual type of argument declared %s",
219 argOidVect[argnum] = argtype;
237 Anum_pg_proc_proargnames,
243 Anum_pg_proc_proargmodes,
252 if (n_arg_names < nargs)
283 Node *subfield = NULL;
285 const char *name2 = NULL;
335 if (strcmp(name1, pinfo->
fname) != 0)
343 else if (nnames == 2 && strcmp(name1, pinfo->
fname) == 0)
397 int paramno = pref->
number;
400 if (paramno <= 0 || paramno > pinfo->
nargs)
411 int paramno,
int location)
419 param->paramtypmod = -1;
431 return (
Node *) param;
441 const char *paramname,
int location)
472 foreach(lc1, queryTree_list)
491 stmt->canSetTag = queryTree->canSetTag;
494 stmt->stmt_len = queryTree->stmt_len;
495 stmt->queryId = queryTree->queryId;
512 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
513 errmsg(
"cannot COPY to/from client in an SQL function")));
517 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
519 errmsg(
"%s is not allowed in an SQL function",
525 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
527 errmsg(
"%s is not allowed in a non-volatile function",
533 preves->
next = newes;
544 if (queryTree->canSetTag)
550 eslist =
lappend(eslist, firstes);
594 List *queryTree_list;
624 elog(
ERROR,
"cache lookup failed for function %u", foid);
646 fcache->
returnsSet = procedureStruct->proretset;
650 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
670 Anum_pg_proc_prosqlbody,
682 queryTree_list =
NIL;
686 List *stored_query_list;
694 foreach(lc, stored_query_list)
697 List *queryTree_sublist;
701 queryTree_list =
lappend(queryTree_list, queryTree_sublist);
706 List *raw_parsetree_list;
710 foreach(lc, raw_parsetree_list)
713 List *queryTree_sublist;
720 queryTree_list =
lappend(queryTree_list, queryTree_sublist);
750 procedureStruct->prokind,
761 if (rettype != VOIDOID)
895 uint64 count = (es->
lazyEval) ? 1 : 0;
934 int nargs = fcinfo->
nargs;
952 for (
int i = 0;
i < nargs;
i++)
1037 bool pushed_snapshot;
1048 sqlerrcontext.
arg = fcinfo->flinfo;
1053 if (fcinfo->flinfo->fn_retset)
1067 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1068 errmsg(
"set-valued function called in context that cannot accept a set")));
1074 randomAccess =
false;
1090 fcinfo->flinfo->fn_extra = NULL;
1118 foreach(eslc, eslist)
1164 pushed_snapshot =
false;
1180 if (!pushed_snapshot)
1183 pushed_snapshot =
true;
1195 pushed_snapshot =
true;
1229 eslc =
lnext(eslist, eslc);
1241 if (pushed_snapshot)
1244 pushed_snapshot =
false;
1267 elog(
ERROR,
"failed to fetch lazy-eval tuple");
1270 fcache, oldcontext);
1304 fcinfo->isnull =
true;
1330 fcinfo->isnull =
true;
1354 fcache, oldcontext);
1357 fcinfo->isnull =
true;
1365 fcinfo->isnull =
true;
1374 if (pushed_snapshot)
1410 int syntaxerrposition;
1416 if (fcache == NULL || fcache->
fname == NULL)
1423 if (syntaxerrposition > 0 && fcache->
src != NULL)
1452 errcontext(
"SQL function \"%s\" statement %d",
1453 fcache->
fname, query_num);
1539 foreach(lc, queryTreeLists)
1544 foreach(lc2, sublist)
1562 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1563 errmsg(
"calling procedures with output arguments is not supported in SQL functions")));
1612 bool insertDroppedCols,
1613 List **resultTargetList)
1615 bool is_tuple_result =
false;
1620 bool tlist_is_modifiable;
1623 bool upper_tlist_nontrivial =
false;
1626 if (resultTargetList)
1627 *resultTargetList =
NIL;
1633 if (rettype == VOIDOID)
1647 foreach(lc, queryTreeLists)
1652 foreach(lc2, sublist)
1678 tlist =
parse->targetList;
1680 tlist_is_modifiable = (
parse->setOperations == NULL);
1687 parse->returningList)
1689 tlist =
parse->returningList;
1691 tlist_is_modifiable =
true;
1697 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1698 errmsg(
"return type mismatch in function declared to return %s",
1700 errdetail(
"Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
1721 if (fn_typtype == TYPTYPE_BASE ||
1722 fn_typtype == TYPTYPE_DOMAIN ||
1723 fn_typtype == TYPTYPE_ENUM ||
1724 fn_typtype == TYPTYPE_RANGE ||
1725 fn_typtype == TYPTYPE_MULTIRANGE)
1735 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1736 errmsg(
"return type mismatch in function declared to return %s",
1738 errdetail(
"Final statement must return exactly one column.")));
1745 tlist_is_modifiable,
1747 &upper_tlist_nontrivial))
1749 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1750 errmsg(
"return type mismatch in function declared to return %s",
1755 else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
1793 if (tlistlen == 1 && prokind != PROKIND_PROCEDURE)
1799 tlist_is_modifiable,
1801 &upper_tlist_nontrivial))
1804 goto tlist_coercion_finished;
1812 if (rettupdesc == NULL)
1815 if (resultTargetList)
1816 *resultTargetList = tlist;
1826 tupnatts = rettupdesc->
natts;
1842 if (colindex > tupnatts)
1844 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1845 errmsg(
"return type mismatch in function declared to return %s",
1847 errdetail(
"Final statement returns too many columns.")));
1849 if (attr->attisdropped && insertDroppedCols)
1861 upper_tlist =
lappend(upper_tlist,
1866 upper_tlist_nontrivial =
true;
1868 }
while (attr->attisdropped);
1872 attr->atttypid, attr->atttypmod,
1873 tlist_is_modifiable,
1875 &upper_tlist_nontrivial))
1877 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1878 errmsg(
"return type mismatch in function declared to return %s",
1880 errdetail(
"Final statement returns %s instead of %s at column %d.",
1887 for (colindex++; colindex <= tupnatts; colindex++)
1891 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1892 errmsg(
"return type mismatch in function declared to return %s",
1894 errdetail(
"Final statement returns too few columns.")));
1895 if (insertDroppedCols)
1907 upper_tlist =
lappend(upper_tlist,
1912 upper_tlist_nontrivial =
true;
1917 is_tuple_result =
true;
1921 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1922 errmsg(
"return type %s is not supported for SQL functions",
1925 tlist_coercion_finished:
1933 if (upper_tlist_nontrivial)
1945 newquery->querySource =
parse->querySource;
1946 newquery->canSetTag =
true;
1951 foreach(lc,
parse->targetList)
1958 makeString(tle->resname ? tle->resname :
""));
1965 rte->eref = rte->alias =
makeAlias(
"*SELECT*", colnames);
1966 rte->lateral =
false;
1968 rte->inFromCl =
true;
1976 lfirst(parse_cell) = newquery;
1980 if (resultTargetList)
1981 *resultTargetList = upper_tlist;
1983 return is_tuple_result;
2000 bool tlist_is_modifiable,
2002 bool *upper_tlist_nontrivial)
2020 res_type, res_typmod,
2024 if (cast_result == NULL)
2027 src_tle->
expr = (
Expr *) cast_result;
2039 res_type, res_typmod,
2043 if (cast_result == NULL)
2047 if (cast_result != (
Node *) var)
2048 *upper_tlist_nontrivial =
true;
2049 new_tle_expr = (
Expr *) cast_result;
2053 src_tle->resname,
false);
2054 *upper_tlist =
lappend(*upper_tlist, new_tle);
#define TextDatumGetCString(d)
#define Assert(condition)
uint32 LocalTransactionId
#define OidIsValid(objectId)
Datum datumCopy(Datum value, bool typByVal, int typLen)
DestReceiver * None_Receiver
DestReceiver * CreateDestReceiver(CommandDest dest)
int internalerrquery(const char *query)
int internalerrposition(int cursorpos)
int errdetail(const char *fmt,...)
ErrorContextCallback * error_context_stack
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errposition(int cursorpos)
#define ereport(elevel,...)
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
JunkFilter * ExecInitJunkFilterConversion(List *targetList, TupleDesc cleanTupType, TupleTableSlot *slot)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
void ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsMinimalTuple
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void UnregisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
int ExecCleanTargetListLength(List *targetlist)
@ SFRM_Materialize_Preferred
@ SFRM_Materialize_Random
#define EXEC_FLAG_SKIP_TRIGGERS
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
Oid get_call_expr_argtype(Node *expr, int argnum)
#define PG_GET_COLLATION()
int get_func_input_arg_names(Datum proargnames, Datum proargmodes, char ***arg_names)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Datum fmgr_sql(PG_FUNCTION_ARGS)
static List * init_execution_state(List *queryTree_list, SQLFunctionCachePtr fcache, bool lazyEvalOK)
void check_sql_fn_statements(List *queryTreeLists)
static Node * sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo, const char *paramname, int location)
static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
static Node * sql_fn_param_ref(ParseState *pstate, ParamRef *pref)
static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
static void postquel_end(execution_state *es)
static void postquel_sub_params(SQLFunctionCachePtr fcache, FunctionCallInfo fcinfo)
static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
struct execution_state execution_state
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
DestReceiver * CreateSQLFunctionDestReceiver(void)
static Node * sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
static void sqlfunction_destroy(DestReceiver *self)
static Datum postquel_get_single_result(TupleTableSlot *slot, FunctionCallInfo fcinfo, SQLFunctionCachePtr fcache, MemoryContext resultcontext)
static void sql_exec_error_callback(void *arg)
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols, List **resultTargetList)
static void sqlfunction_shutdown(DestReceiver *self)
static Node * sql_fn_make_param(SQLFunctionParseInfoPtr pinfo, int paramno, int location)
static void init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK)
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
static void ShutdownSQLFunction(Datum arg)
static bool coerce_fn_result_column(TargetEntry *src_tle, Oid res_type, int32 res_typmod, bool tlist_is_modifiable, List **upper_tlist, bool *upper_tlist_nontrivial)
SQLFunctionCache * SQLFunctionCachePtr
SQLFunctionParseInfo * SQLFunctionParseInfoPtr
#define HeapTupleIsValid(tuple)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
bool type_is_rowtype(Oid typid)
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Oid get_typcollation(Oid typid)
int16 get_typlen(Oid typid)
char get_typtype(Oid typid)
Alias * makeAlias(const char *aliasname, List *colnames)
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
FromExpr * makeFromExpr(List *fromlist, Node *quals)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
Oid exprType(const Node *expr)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
ParamListInfo makeParamList(int numParams)
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
#define CURSOR_OPT_PARALLEL_OK
FormData_pg_attribute * Form_pg_attribute
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
static ListCell * lnext(const List *l, const ListCell *c)
FormData_pg_proc * Form_pg_proc
List * pg_parse_query(const char *query_string)
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
List * pg_rewrite_query(Query *query)
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
void FreeQueryDesc(QueryDesc *qdesc)
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
MemoryContextSwitchTo(old_ctx)
void * stringToNode(const char *str)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
Snapshot GetTransactionSnapshot(void)
void PushActiveSnapshot(Snapshot snapshot)
void UpdateActiveSnapshotCommandId(void)
bool ActiveSnapshotSet(void)
void PopActiveSnapshot(void)
Snapshot GetActiveSnapshot(void)
struct ErrorContextCallback * previous
void(* callback)(void *arg)
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
TupleDesc jf_cleanTupType
TupleTableSlot * jf_resultSlot
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
ParseParamRefHook p_paramref_hook
PreParseColumnRefHook p_pre_columnref_hook
PostParseColumnRefHook p_post_columnref_hook
PlannedStmt * plannedstmt
QueryEnvironment * queryEnv
SetFunctionReturnMode returnMode
Tuplestorestate * setResult
SQLFunctionParseInfoPtr pinfo
TupleDesc tts_tupleDescriptor
void(* rDestroy)(DestReceiver *self)
struct execution_state * next
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
#define TupleDescAttr(tupdesc, i)
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
void tuplestore_clear(Tuplestorestate *state)
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
void tuplestore_end(Tuplestorestate *state)
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
bool CommandIsReadOnly(PlannedStmt *pstmt)
static const char * CreateCommandName(Node *parsetree)
String * makeString(char *str)
SubTransactionId GetCurrentSubTransactionId(void)
void CommandCounterIncrement(void)
bool SubTransactionIsActive(SubTransactionId subxid)