PostgreSQL Source Code  git master
fastpath.h File Reference
#include "lib/stringinfo.h"
Include dependency graph for fastpath.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void HandleFunctionRequest (StringInfo msgBuf)
 

Function Documentation

◆ HandleFunctionRequest()

void HandleFunctionRequest ( StringInfo  msgBuf)

Definition at line 188 of file fastpath.c.

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), ACLCHECK_OK, CHECK_FOR_INTERRUPTS, check_log_duration(), ereport, errcode(), errmsg(), ERROR, fetch_fp_info(), fp_info::flinfo, FmgrInfo::fn_strict, fp_info::fname, FUNC_MAX_ARGS, FunctionCallInvoke, get_func_name(), get_namespace_name(), GetTransactionSnapshot(), GetUserId(), i, InitFunctionCallInfoData, InvalidOid, InvokeFunctionExecuteHook, InvokeNamespaceSearchHook, IsAbortedTransactionBlockState(), LOCAL_FCINFO, LOG, log_statement, LOGSTMT_ALL, OBJECT_FUNCTION, OBJECT_SCHEMA, parse_fcall_arguments(), pg_namespace_aclcheck(), pg_proc_aclcheck(), PopActiveSnapshot(), pq_getmsgend(), pq_getmsgint(), PushActiveSnapshot(), fp_info::rettype, and SendFunctionResult().

Referenced by PostgresMain().

189 {
190  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
191  Oid fid;
192  AclResult aclresult;
193  int16 rformat;
194  Datum retval;
195  struct fp_info my_fp;
196  struct fp_info *fip;
197  bool callit;
198  bool was_logged = false;
199  char msec_str[32];
200 
201  /*
202  * We only accept COMMIT/ABORT if we are in an aborted transaction, and
203  * COMMIT/ABORT cannot be executed through the fastpath interface.
204  */
206  ereport(ERROR,
207  (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
208  errmsg("current transaction is aborted, "
209  "commands ignored until end of transaction block")));
210 
211  /*
212  * Now that we know we are in a valid transaction, set snapshot in case
213  * needed by function itself or one of the datatype I/O routines.
214  */
216 
217  /*
218  * Begin parsing the buffer contents.
219  */
220  fid = (Oid) pq_getmsgint(msgBuf, 4); /* function oid */
221 
222  /*
223  * There used to be a lame attempt at caching lookup info here. Now we
224  * just do the lookups on every call.
225  */
226  fip = &my_fp;
227  fetch_fp_info(fid, fip);
228 
229  /* Log as soon as we have the function OID and name */
230  if (log_statement == LOGSTMT_ALL)
231  {
232  ereport(LOG,
233  (errmsg("fastpath function call: \"%s\" (OID %u)",
234  fip->fname, fid)));
235  was_logged = true;
236  }
237 
238  /*
239  * Check permission to access and call function. Since we didn't go
240  * through a normal name lookup, we need to check schema usage too.
241  */
242  aclresult = pg_namespace_aclcheck(fip->namespace, GetUserId(), ACL_USAGE);
243  if (aclresult != ACLCHECK_OK)
244  aclcheck_error(aclresult, OBJECT_SCHEMA,
245  get_namespace_name(fip->namespace));
246  InvokeNamespaceSearchHook(fip->namespace, true);
247 
248  aclresult = pg_proc_aclcheck(fid, GetUserId(), ACL_EXECUTE);
249  if (aclresult != ACLCHECK_OK)
250  aclcheck_error(aclresult, OBJECT_FUNCTION,
251  get_func_name(fid));
253 
254  /*
255  * Prepare function call info block and insert arguments.
256  *
257  * Note: for now we pass collation = InvalidOid, so collation-sensitive
258  * functions can't be called this way. Perhaps we should pass
259  * DEFAULT_COLLATION_OID, instead?
260  */
261  InitFunctionCallInfoData(*fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
262 
263  rformat = parse_fcall_arguments(msgBuf, fip, fcinfo);
264 
265  /* Verify we reached the end of the message where expected. */
266  pq_getmsgend(msgBuf);
267 
268  /*
269  * If func is strict, must not call it for null args.
270  */
271  callit = true;
272  if (fip->flinfo.fn_strict)
273  {
274  int i;
275 
276  for (i = 0; i < fcinfo->nargs; i++)
277  {
278  if (fcinfo->args[i].isnull)
279  {
280  callit = false;
281  break;
282  }
283  }
284  }
285 
286  if (callit)
287  {
288  /* Okay, do it ... */
289  retval = FunctionCallInvoke(fcinfo);
290  }
291  else
292  {
293  fcinfo->isnull = true;
294  retval = (Datum) 0;
295  }
296 
297  /* ensure we do at least one CHECK_FOR_INTERRUPTS per function call */
299 
300  SendFunctionResult(retval, fcinfo->isnull, fip->rettype, rformat);
301 
302  /* We no longer need the snapshot */
304 
305  /*
306  * Emit duration logging if appropriate.
307  */
308  switch (check_log_duration(msec_str, was_logged))
309  {
310  case 1:
311  ereport(LOG,
312  (errmsg("duration: %s ms", msec_str)));
313  break;
314  case 2:
315  ereport(LOG,
316  (errmsg("duration: %s ms fastpath function call: \"%s\" (OID %u)",
317  msec_str, fip->fname, fid)));
318  break;
319  }
320 }
signed short int16
Definition: c.h:428
FmgrInfo flinfo
Definition: fastpath.c:51
char fname[NAMEDATALEN]
Definition: fastpath.c:55
Oid rettype
Definition: fastpath.c:52
Oid GetUserId(void)
Definition: miscinit.c:495
bool IsAbortedTransactionBlockState(void)
Definition: xact.c:392
int errcode(int sqlerrcode)
Definition: elog.c:698
static void SendFunctionResult(Datum retval, bool isnull, Oid rettype, int16 format)
Definition: fastpath.c:67
void PopActiveSnapshot(void)
Definition: snapmgr.c:774
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4756
#define FUNC_MAX_ARGS
#define InvokeNamespaceSearchHook(objectId, ereport_on_violation)
Definition: objectaccess.h:186
int check_log_duration(char *msec_str, bool was_logged)
Definition: postgres.c:2324
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
bool fn_strict
Definition: fmgr.h:61
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1579
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:680
#define ACL_USAGE
Definition: parsenodes.h:90
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
static int16 parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, FunctionCallInfo fcinfo)
Definition: fastpath.c:329
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
int log_statement
Definition: postgres.c:97
static void fetch_fp_info(Oid func_id, struct fp_info *fip)
Definition: fastpath.c:119
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ACL_EXECUTE
Definition: parsenodes.h:89
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4718
int i
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:637