PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
funccache.h File Reference
#include "access/htup_details.h"
#include "fmgr.h"
#include "storage/itemptr.h"
Include dependency graph for funccache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  CachedFunctionHashKey
 
struct  CachedFunction
 

Typedefs

typedef void(* CachedFunctionCompileCallback) (FunctionCallInfo fcinfo, HeapTuple procTup, const struct CachedFunctionHashKey *hashkey, struct CachedFunction *function, bool forValidator)
 
typedef void(* CachedFunctionDeleteCallback) (struct CachedFunction *cfunc)
 
typedef struct CachedFunctionHashKey CachedFunctionHashKey
 
typedef struct CachedFunction CachedFunction
 

Functions

CachedFunctioncached_function_compile (FunctionCallInfo fcinfo, CachedFunction *function, CachedFunctionCompileCallback ccallback, CachedFunctionDeleteCallback dcallback, Size cacheEntrySize, bool includeResultType, bool forValidator)
 
void cfunc_resolve_polymorphic_argtypes (int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
 

Typedef Documentation

◆ CachedFunction

◆ CachedFunctionCompileCallback

typedef void(* CachedFunctionCompileCallback) (FunctionCallInfo fcinfo, HeapTuple procTup, const struct CachedFunctionHashKey *hashkey, struct CachedFunction *function, bool forValidator)

Definition at line 35 of file funccache.h.

◆ CachedFunctionDeleteCallback

typedef void(* CachedFunctionDeleteCallback) (struct CachedFunction *cfunc)

Definition at line 45 of file funccache.h.

◆ CachedFunctionHashKey

Function Documentation

◆ cached_function_compile()

CachedFunction * cached_function_compile ( FunctionCallInfo  fcinfo,
CachedFunction function,
CachedFunctionCompileCallback  ccallback,
CachedFunctionDeleteCallback  dcallback,
Size  cacheEntrySize,
bool  includeResultType,
bool  forValidator 
)

Definition at line 480 of file funccache.c.

487{
488 Oid funcOid = fcinfo->flinfo->fn_oid;
489 HeapTuple procTup;
490 Form_pg_proc procStruct;
491 CachedFunctionHashKey hashkey;
492 bool function_valid = false;
493 bool hashkey_valid = false;
494
495 /*
496 * Lookup the pg_proc tuple by Oid; we'll need it in any case
497 */
498 procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
499 if (!HeapTupleIsValid(procTup))
500 elog(ERROR, "cache lookup failed for function %u", funcOid);
501 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
502
503 /*
504 * Do we already have a cache entry for the current FmgrInfo? If not, try
505 * to find one in the hash table.
506 */
507recheck:
508 if (!function)
509 {
510 /* Compute hashkey using function signature and actual arg types */
511 compute_function_hashkey(fcinfo, procStruct, &hashkey,
512 cacheEntrySize, includeResultType,
513 forValidator);
514 hashkey_valid = true;
515
516 /* And do the lookup */
518 }
519
520 if (function)
521 {
522 /* We have a compiled function, but is it still valid? */
523 if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
524 ItemPointerEquals(&function->fn_tid, &procTup->t_self))
525 function_valid = true;
526 else
527 {
528 /*
529 * Nope, so remove it from hashtable and try to drop associated
530 * storage (if not done already).
531 */
533
534 /*
535 * If the function isn't in active use then we can overwrite the
536 * func struct with new data, allowing any other existing fn_extra
537 * pointers to make use of the new definition on their next use.
538 * If it is in use then just leave it alone and make a new one.
539 * (The active invocations will run to completion using the
540 * previous definition, and then the cache entry will just be
541 * leaked; doesn't seem worth adding code to clean it up, given
542 * what a corner case this is.)
543 *
544 * If we found the function struct via fn_extra then it's possible
545 * a replacement has already been made, so go back and recheck the
546 * hashtable.
547 */
548 if (function->use_count != 0)
549 {
550 function = NULL;
551 if (!hashkey_valid)
552 goto recheck;
553 }
554 }
555 }
556
557 /*
558 * If the function wasn't found or was out-of-date, we have to compile it.
559 */
560 if (!function_valid)
561 {
562 /*
563 * Calculate hashkey if we didn't already; we'll need it to store the
564 * completed function.
565 */
566 if (!hashkey_valid)
567 compute_function_hashkey(fcinfo, procStruct, &hashkey,
568 cacheEntrySize, includeResultType,
569 forValidator);
570
571 /*
572 * Create the new function struct, if not done already. The function
573 * structs are never thrown away, so keep them in TopMemoryContext.
574 */
575 Assert(cacheEntrySize >= sizeof(CachedFunction));
576 if (function == NULL)
577 {
580 }
581 else
582 {
583 /* re-using a previously existing struct, so clear it out */
584 memset(function, 0, cacheEntrySize);
585 }
586
587 /*
588 * Fill in the CachedFunction part. fn_hashkey and use_count remain
589 * zeroes for now.
590 */
591 function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
592 function->fn_tid = procTup->t_self;
593 function->dcallback = dcallback;
594
595 /*
596 * Do the hard, language-specific part.
597 */
598 ccallback(fcinfo, procTup, &hashkey, function, forValidator);
599
600 /*
601 * Add the completed struct to the hash table.
602 */
604 }
605
606 ReleaseSysCache(procTup);
607
608 /*
609 * Finally return the compiled function
610 */
611 return function;
612}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
static void compute_function_hashkey(FunctionCallInfo fcinfo, Form_pg_proc procStruct, CachedFunctionHashKey *hashkey, Size cacheEntrySize, bool includeResultType, bool forValidator)
Definition: funccache.c:247
static void cfunc_hashtable_insert(CachedFunction *function, CachedFunctionHashKey *func_key)
Definition: funccache.c:167
static CachedFunction * cfunc_hashtable_lookup(CachedFunctionHashKey *func_key)
Definition: funccache.c:146
static void delete_function(CachedFunction *func)
Definition: funccache.c:433
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)
Definition: htup_details.h:318
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:35
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1290
MemoryContext TopMemoryContext
Definition: mcxt.c:165
on_exit_nicely_callback function
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
unsigned int Oid
Definition: postgres_ext.h:30
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo * flinfo
Definition: fmgr.h:87
ItemPointerData t_self
Definition: htup.h:65
HeapTupleHeader t_data
Definition: htup.h:68
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References Assert(), cfunc_hashtable_insert(), cfunc_hashtable_lookup(), compute_function_hashkey(), delete_function(), elog, ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_oid, function, GETSTRUCT(), HeapTupleHeaderGetRawXmin(), HeapTupleIsValid, ItemPointerEquals(), MemoryContextAllocZero(), ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache1(), HeapTupleData::t_data, HeapTupleData::t_self, and TopMemoryContext.

Referenced by init_sql_fcache(), and plpgsql_compile().

◆ cfunc_resolve_polymorphic_argtypes()

void cfunc_resolve_polymorphic_argtypes ( int  numargs,
Oid argtypes,
char *  argmodes,
Node call_expr,
bool  forValidator,
const char *  proname 
)

Definition at line 348 of file funccache.c.

352{
353 int i;
354
355 if (!forValidator)
356 {
357 int inargno;
358
359 /* normal case, pass to standard routine */
360 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
361 call_expr))
363 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
364 errmsg("could not determine actual argument "
365 "type for polymorphic function \"%s\"",
366 proname)));
367 /* also, treat RECORD inputs (but not outputs) as polymorphic */
368 inargno = 0;
369 for (i = 0; i < numargs; i++)
370 {
371 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
372
373 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
374 continue;
375 if (argtypes[i] == RECORDOID || argtypes[i] == RECORDARRAYOID)
376 {
377 Oid resolvedtype = get_call_expr_argtype(call_expr,
378 inargno);
379
380 if (OidIsValid(resolvedtype))
381 argtypes[i] = resolvedtype;
382 }
383 inargno++;
384 }
385 }
386 else
387 {
388 /* special validation case (no need to do anything for RECORD) */
389 for (i = 0; i < numargs; i++)
390 {
391 switch (argtypes[i])
392 {
393 case ANYELEMENTOID:
394 case ANYNONARRAYOID:
395 case ANYENUMOID: /* XXX dubious */
396 case ANYCOMPATIBLEOID:
397 case ANYCOMPATIBLENONARRAYOID:
398 argtypes[i] = INT4OID;
399 break;
400 case ANYARRAYOID:
401 case ANYCOMPATIBLEARRAYOID:
402 argtypes[i] = INT4ARRAYOID;
403 break;
404 case ANYRANGEOID:
405 case ANYCOMPATIBLERANGEOID:
406 argtypes[i] = INT4RANGEOID;
407 break;
408 case ANYMULTIRANGEOID:
409 argtypes[i] = INT4MULTIRANGEOID;
410 break;
411 default:
412 break;
413 }
414 }
415 }
416}
#define OidIsValid(objectId)
Definition: c.h:746
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:149
Oid get_call_expr_argtype(Node *expr, int argnum)
Definition: fmgr.c:1929
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:1064
int i
Definition: isn.c:77
NameData proname
Definition: pg_proc.h:35

References ereport, errcode(), errmsg(), ERROR, get_call_expr_argtype(), i, OidIsValid, proname, and resolve_polymorphic_argtypes().

Referenced by compute_function_hashkey(), and plpgsql_compile_callback().