|
|
|
src/backend/utils/fmgr/README
|
|
|
|
|
|
|
|
Function Manager
|
|
|
|
================
|
|
|
|
|
|
|
|
[This file originally explained the transition from the V0 to the V1
|
|
|
|
interface. Now it just explains some internals and rationale for the V1
|
|
|
|
interface, while the V0 interface has been removed.]
|
|
|
|
|
|
|
|
The V1 Function-Manager Interface
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
The core of the design is data structures for representing the result of a
|
|
|
|
function lookup and for representing the parameters passed to a specific
|
|
|
|
function invocation. (We want to keep function lookup separate from
|
|
|
|
function call, since many parts of the system apply the same function over
|
|
|
|
and over; the lookup overhead should be paid once per query, not once per
|
|
|
|
tuple.)
|
|
|
|
|
|
|
|
|
|
|
|
When a function is looked up in pg_proc, the result is represented as
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
PGFunction fn_addr; /* pointer to function or handler to be called */
|
|
|
|
Oid fn_oid; /* OID of function (NOT of handler, if any) */
|
|
|
|
short fn_nargs; /* number of input args (0..FUNC_MAX_ARGS) */
|
|
|
|
bool fn_strict; /* function is "strict" (NULL in => NULL out) */
|
|
|
|
bool fn_retset; /* function returns a set (over multiple calls) */
|
|
|
|
unsigned char fn_stats; /* collect stats if track_functions > this */
|
|
|
|
void *fn_extra; /* extra space for use by handler */
|
|
|
|
MemoryContext fn_mcxt; /* memory context to store fn_extra in */
|
|
|
|
Node *fn_expr; /* expression parse tree for call, or NULL */
|
|
|
|
} FmgrInfo;
|
|
|
|
|
|
|
|
For an ordinary built-in function, fn_addr is just the address of the C
|
|
|
|
routine that implements the function. Otherwise it is the address of a
|
|
|
|
handler for the class of functions that includes the target function.
|
|
|
|
The handler can use the function OID and perhaps also the fn_extra slot
|
|
|
|
to find the specific code to execute. (fn_oid = InvalidOid can be used
|
|
|
|
to denote a not-yet-initialized FmgrInfo struct. fn_extra will always
|
|
|
|
be NULL when an FmgrInfo is first filled by the function lookup code, but
|
|
|
|
a function handler could set it to avoid making repeated lookups of its
|
|
|
|
own when the same FmgrInfo is used repeatedly during a query.) fn_nargs
|
|
|
|
is the number of arguments expected by the function, fn_strict is its
|
|
|
|
strictness flag, and fn_retset shows whether it returns a set; all of
|
|
|
|
these values come from the function's pg_proc entry. fn_stats is also
|
|
|
|
set up to control whether or not to track runtime statistics for calling
|
|
|
|
this function.
|
|
|
|
|
|
|
|
If the function is being called as part of a SQL expression, fn_expr will
|
|
|
|
point to the expression parse tree for the function call; this can be used
|
|
|
|
to extract parse-time knowledge about the actual arguments. Note that this
|
|
|
|
field really is information about the arguments rather than information
|
|
|
|
about the function, but it's proven to be more convenient to keep it in
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
FmgrInfo than in FunctionCallInfoBaseData where it might more logically go.
|
|
|
|
|
|
|
|
|
|
|
|
During a call of a function, the following data structure is created
|
|
|
|
and passed to the function:
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
FmgrInfo *flinfo; /* ptr to lookup info used for this call */
|
|
|
|
Node *context; /* pass info about context of call */
|
|
|
|
Node *resultinfo; /* pass or return extra info about result */
|
|
|
|
Oid fncollation; /* collation for function to use */
|
|
|
|
bool isnull; /* function must set true if result is NULL */
|
|
|
|
short nargs; /* # arguments actually passed */
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
NullableDatum args[]; /* Arguments passed to function */
|
|
|
|
} FunctionCallInfoBaseData;
|
|
|
|
typedef FunctionCallInfoBaseData* FunctionCallInfo;
|
|
|
|
|
|
|
|
flinfo points to the lookup info used to make the call. Ordinary functions
|
|
|
|
will probably ignore this field, but function class handlers will need it
|
|
|
|
to find out the OID of the specific function being called.
|
|
|
|
|
|
|
|
context is NULL for an "ordinary" function call, but may point to additional
|
|
|
|
info when the function is called in certain contexts. (For example, the
|
|
|
|
trigger manager will pass information about the current trigger event here.)
|
|
|
|
If context is used, it should point to some subtype of Node; the particular
|
|
|
|
kind of context is indicated by the node type field. (A callee should
|
|
|
|
always check the node type before assuming it knows what kind of context is
|
|
|
|
being passed.) fmgr itself puts no other restrictions on the use of this
|
|
|
|
field.
|
|
|
|
|
|
|
|
resultinfo is NULL when calling any function from which a simple Datum
|
|
|
|
result is expected. It may point to some subtype of Node if the function
|
|
|
|
returns more than a Datum. (For example, resultinfo is used when calling a
|
|
|
|
function that returns a set, as discussed below.) Like the context field,
|
|
|
|
resultinfo is a hook for expansion; fmgr itself doesn't constrain the use
|
|
|
|
of the field.
|
|
|
|
|
|
|
|
fncollation is the input collation derived by the parser, or InvalidOid
|
|
|
|
when there are no inputs of collatable types or they don't share a common
|
|
|
|
collation. This is effectively a hidden additional argument, which
|
|
|
|
collation-sensitive functions can use to determine their behavior.
|
|
|
|
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
nargs and args[] hold the arguments being passed to the function.
|
|
|
|
Notice that all the arguments passed to a function (as well as its result
|
|
|
|
value) will now uniformly be of type Datum. As discussed below, callers
|
|
|
|
and callees should apply the standard Datum-to-and-from-whatever macros
|
|
|
|
to convert to the actual argument types of a particular function. The
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
value in args[i].value is unspecified when args[i].isnull is true.
|
|
|
|
|
|
|
|
It is generally the responsibility of the caller to ensure that the
|
|
|
|
number of arguments passed matches what the callee is expecting; except
|
|
|
|
for callees that take a variable number of arguments, the callee will
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
typically ignore the nargs field and just grab values from args[].
|
|
|
|
|
|
|
|
The isnull field will be initialized to "false" before the call. On
|
|
|
|
return from the function, isnull is the null flag for the function result:
|
|
|
|
if it is true the function's result is NULL, regardless of the actual
|
|
|
|
function return value. Note that simple "strict" functions can ignore
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
both isnull and args[i].isnull, since they won't even get called when there
|
|
|
|
are any TRUE values in args[].isnull.
|
|
|
|
|
|
|
|
FunctionCallInfo replaces FmgrValues plus a bunch of ad-hoc parameter
|
|
|
|
conventions, global variables (fmgr_pl_finfo and CurrentTriggerData at
|
|
|
|
least), and other uglinesses.
|
|
|
|
|
|
|
|
|
|
|
|
Callees, whether they be individual functions or function handlers,
|
|
|
|
shall always have this signature:
|
|
|
|
|
|
|
|
Datum function (FunctionCallInfo fcinfo);
|
|
|
|
|
|
|
|
which is represented by the typedef
|
|
|
|
|
|
|
|
typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
|
|
|
|
|
|
|
|
The function is responsible for setting fcinfo->isnull appropriately
|
|
|
|
as well as returning a result represented as a Datum. Note that since
|
|
|
|
all callees will now have exactly the same signature, and will be called
|
|
|
|
through a function pointer declared with exactly that signature, we
|
|
|
|
should have no portability or optimization problems.
|
|
|
|
|
|
|
|
|
|
|
|
Function Coding Conventions
|
|
|
|
---------------------------
|
|
|
|
|
|
|
|
Here are the proposed macros and coding conventions:
|
|
|
|
|
|
|
|
The definition of an fmgr-callable function will always look like
|
|
|
|
|
|
|
|
Datum
|
|
|
|
function_name(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
"PG_FUNCTION_ARGS" just expands to "FunctionCallInfo fcinfo". The main
|
|
|
|
reason for using this macro is to make it easy for scripts to spot function
|
|
|
|
definitions. However, if we ever decide to change the calling convention
|
|
|
|
again, it might come in handy to have this macro in place.
|
|
|
|
|
|
|
|
A nonstrict function is responsible for checking whether each individual
|
|
|
|
argument is null or not, which it can do with PG_ARGISNULL(n) (which is
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
just "fcinfo->args[n].isnull"). It should avoid trying to fetch the value
|
|
|
|
of any argument that is null.
|
|
|
|
|
|
|
|
Both strict and nonstrict functions can return NULL, if needed, with
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
which expands to
|
|
|
|
{ fcinfo->isnull = true; return (Datum) 0; }
|
|
|
|
|
|
|
|
Argument values are ordinarily fetched using code like
|
|
|
|
int32 name = PG_GETARG_INT32(number);
|
|
|
|
|
|
|
|
For float4, float8, and int8, the PG_GETARG macros will hide whether the
|
|
|
|
types are pass-by-value or pass-by-reference. For example, if float8 is
|
|
|
|
pass-by-reference then PG_GETARG_FLOAT8 expands to
|
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/20180605172952.x34m5uz6ju6enaem@alap3.anarazel.de
7 years ago
|
|
|
(* (float8 *) DatumGetPointer(fcinfo->args[number].value))
|
|
|
|
and would typically be called like this:
|
|
|
|
float8 arg = PG_GETARG_FLOAT8(0);
|
|
|
|
For what are now historical reasons, the float-related typedefs and macros
|
|
|
|
express the type width in bytes (4 or 8), whereas we prefer to label the
|
|
|
|
widths of integer types in bits.
|
|
|
|
|
|
|
|
Non-null values are returned with a PG_RETURN_XXX macro of the appropriate
|
|
|
|
type. For example, PG_RETURN_INT32 expands to
|
|
|
|
return Int32GetDatum(x)
|
|
|
|
PG_RETURN_FLOAT4, PG_RETURN_FLOAT8, and PG_RETURN_INT64 hide whether their
|
|
|
|
data types are pass-by-value or pass-by-reference, by doing a palloc if
|
|
|
|
needed.
|
|
|
|
|
|
|
|
fmgr.h will provide PG_GETARG and PG_RETURN macros for all the basic data
|
|
|
|
types. Modules or header files that define specialized SQL datatypes
|
|
|
|
(eg, timestamp) should define appropriate macros for those types, so that
|
|
|
|
functions manipulating the types can be coded in the standard style.
|
|
|
|
|
|
|
|
For non-primitive data types (particularly variable-length types) it won't
|
|
|
|
be very practical to hide the pass-by-reference nature of the data type,
|
|
|
|
so the PG_GETARG and PG_RETURN macros for those types won't do much more
|
|
|
|
than DatumGetPointer/PointerGetDatum plus the appropriate typecast (but see
|
|
|
|
TOAST discussion, below). Functions returning such types will need to
|
|
|
|
palloc() their result space explicitly. I recommend naming the GETARG and
|
|
|
|
RETURN macros for such types to end in "_P", as a reminder that they
|
|
|
|
produce or take a pointer. For example, PG_GETARG_TEXT_P yields "text *".
|
|
|
|
|
|
|
|
When a function needs to access fcinfo->flinfo or one of the other auxiliary
|
|
|
|
fields of FunctionCallInfo, it should just do it. I doubt that providing
|
|
|
|
syntactic-sugar macros for these cases is useful.
|
|
|
|
|
|
|
|
|
|
|
|
Support for TOAST-Able Data Types
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
For TOAST-able data types, the PG_GETARG macro will deliver a de-TOASTed
|
|
|
|
data value. There might be a few cases where the still-toasted value is
|
|
|
|
wanted, but the vast majority of cases want the de-toasted result, so
|
|
|
|
that will be the default. To get the argument value without causing
|
|
|
|
de-toasting, use PG_GETARG_RAW_VARLENA_P(n).
|
|
|
|
|
|
|
|
Some functions require a modifiable copy of their input values. In these
|
|
|
|
cases, it's silly to do an extra copy step if we copied the data anyway
|
|
|
|
to de-TOAST it. Therefore, each toastable datatype has an additional
|
|
|
|
fetch macro, for example PG_GETARG_TEXT_P_COPY(n), which delivers a
|
|
|
|
guaranteed-fresh copy, combining this with the detoasting step if possible.
|
|
|
|
|
|
|
|
There is also a PG_FREE_IF_COPY(ptr,n) macro, which pfree's the given
|
|
|
|
pointer if and only if it is different from the original value of the n'th
|
|
|
|
argument. This can be used to free the de-toasted value of the n'th
|
|
|
|
argument, if it was actually de-toasted. Currently, doing this is not
|
|
|
|
necessary for the majority of functions because the core backend code
|
|
|
|
releases temporary space periodically, so that memory leaked in function
|
|
|
|
execution isn't a big problem. However, as of 7.1 memory leaks in
|
|
|
|
functions that are called by index searches will not be cleaned up until
|
|
|
|
end of transaction. Therefore, functions that are listed in pg_amop or
|
|
|
|
pg_amproc should be careful not to leak detoasted copies, and so these
|
|
|
|
functions do need to use PG_FREE_IF_COPY() for toastable inputs.
|
|
|
|
|
|
|
|
A function should never try to re-TOAST its result value; it should just
|
|
|
|
deliver an untoasted result that's been palloc'd in the current memory
|
|
|
|
context. When and if the value is actually stored into a tuple, the
|
|
|
|
tuple toaster will decide whether toasting is needed.
|
|
|
|
|
|
|
|
|
|
|
|
Functions Accepting or Returning Sets
|
|
|
|
-------------------------------------
|
|
|
|
|
|
|
|
[ this section revised 29-Aug-2002 for 7.3 ]
|
|
|
|
|
|
|
|
If a function is marked in pg_proc as returning a set, then it is called
|
|
|
|
with fcinfo->resultinfo pointing to a node of type ReturnSetInfo. A
|
|
|
|
function that desires to return a set should raise an error "called in
|
|
|
|
context that does not accept a set result" if resultinfo is NULL or does
|
|
|
|
not point to a ReturnSetInfo node.
|
|
|
|
|
|
|
|
There are currently two modes in which a function can return a set result:
|
|
|
|
value-per-call, or materialize. In value-per-call mode, the function returns
|
|
|
|
one value each time it is called, and finally reports "done" when it has no
|
|
|
|
more values to return. In materialize mode, the function's output set is
|
|
|
|
instantiated in a Tuplestore object; all the values are returned in one call.
|
|
|
|
Additional modes might be added in future.
|
|
|
|
|
|
|
|
ReturnSetInfo contains a field "allowedModes" which is set (by the caller)
|
|
|
|
to a bitmask that's the OR of the modes the caller can support. The actual
|
|
|
|
mode used by the function is returned in another field "returnMode". For
|
|
|
|
backwards-compatibility reasons, returnMode is initialized to value-per-call
|
|
|
|
and need only be changed if the function wants to use a different mode.
|
|
|
|
The function should ereport() if it cannot use any of the modes the caller is
|
|
|
|
willing to support.
|
|
|
|
|
|
|
|
Value-per-call mode works like this: ReturnSetInfo contains a field
|
|
|
|
"isDone", which should be set to one of these values:
|
|
|
|
|
|
|
|
ExprSingleResult /* expression does not return a set */
|
|
|
|
ExprMultipleResult /* this result is an element of a set */
|
|
|
|
ExprEndResult /* there are no more elements in the set */
|
|
|
|
|
|
|
|
(the caller will initialize it to ExprSingleResult). If the function simply
|
|
|
|
returns a Datum without touching ReturnSetInfo, then the call is over and a
|
|
|
|
single-item set has been returned. To return a set, the function must set
|
|
|
|
isDone to ExprMultipleResult for each set element. After all elements have
|
|
|
|
been returned, the next call should set isDone to ExprEndResult and return a
|
|
|
|
null result. (Note it is possible to return an empty set by doing this on
|
|
|
|
the first call.)
|
|
|
|
|
|
|
|
The ReturnSetInfo node also contains a link to the ExprContext within which
|
|
|
|
the function is being evaluated. This is useful for value-per-call functions
|
|
|
|
that need to close down internal state when they are not run to completion:
|
|
|
|
they can register a shutdown callback function in the ExprContext.
|
|
|
|
|
|
|
|
Materialize mode works like this: the function creates a Tuplestore holding
|
|
|
|
the (possibly empty) result set, and returns it. There are no multiple calls.
|
|
|
|
The function must also return a TupleDesc that indicates the tuple structure.
|
|
|
|
The Tuplestore and TupleDesc should be created in the context
|
|
|
|
econtext->ecxt_per_query_memory (note this will *not* be the context the
|
|
|
|
function is called in). The function stores pointers to the Tuplestore and
|
|
|
|
TupleDesc into ReturnSetInfo, sets returnMode to indicate materialize mode,
|
|
|
|
and returns null. isDone is not used and should be left at ExprSingleResult.
|
|
|
|
|
|
|
|
The Tuplestore must be created with randomAccess = true if
|
|
|
|
SFRM_Materialize_Random is set in allowedModes, but it can (and preferably
|
|
|
|
should) be created with randomAccess = false if not. Callers that can support
|
|
|
|
both ValuePerCall and Materialize mode will set SFRM_Materialize_Preferred,
|
|
|
|
or not, depending on which mode they prefer.
|
|
|
|
|
|
|
|
If available, the expected tuple descriptor is passed in ReturnSetInfo;
|
|
|
|
in other contexts the expectedDesc field will be NULL. The function need
|
|
|
|
not pay attention to expectedDesc, but it may be useful in special cases.
|
|
|
|
|
|
|
|
There is no support for functions accepting sets; instead, the function will
|
|
|
|
be called multiple times, once for each element of the input set.
|
|
|
|
|
|
|
|
|
|
|
|
Notes About Function Handlers
|
|
|
|
-----------------------------
|
|
|
|
|
|
|
|
Handlers for classes of functions should find life much easier and
|
|
|
|
cleaner in this design. The OID of the called function is directly
|
|
|
|
reachable from the passed parameters; we don't need the global variable
|
|
|
|
fmgr_pl_finfo anymore. Also, by modifying fcinfo->flinfo->fn_extra,
|
|
|
|
the handler can cache lookup info to avoid repeat lookups when the same
|
|
|
|
function is invoked many times. (fn_extra can only be used as a hint,
|
|
|
|
since callers are not required to re-use an FmgrInfo struct.
|
|
|
|
But in performance-critical paths they normally will do so.)
|
|
|
|
|
|
|
|
If the handler wants to allocate memory to hold fn_extra data, it should
|
|
|
|
NOT do so in CurrentMemoryContext, since the current context may well be
|
|
|
|
much shorter-lived than the context where the FmgrInfo is. Instead,
|
|
|
|
allocate the memory in context flinfo->fn_mcxt, or in a long-lived cache
|
|
|
|
context. fn_mcxt normally points at the context that was
|
|
|
|
CurrentMemoryContext at the time the FmgrInfo structure was created;
|
|
|
|
in any case it is required to be a context at least as long-lived as the
|
|
|
|
FmgrInfo itself.
|