mirror of
https://github.com/postgres/postgres.git
synced 2025-07-12 21:01:52 +03:00
Fix up run-time partition pruning's use of relcache's partition data.
The previous coding saved pointers into the partitioned table's relcache entry, but then closed the relcache entry, causing those pointers to nominally become dangling. Actual trouble would be seen in the field only if a relcache flush occurred mid-query, but that's hardly out of the question. While we could fix this by copying all the data in question at query start, it seems better to just hold the relcache entry open for the whole query. While at it, improve the handling of support-function lookups: do that once per query not once per pruning test. There's still something to be desired here, in that we fail to exploit the possibility of caching data across queries in the fn_extra fields of the relcache's FmgrInfo structs, which could happen if we just used those structs in-place rather than copying them. However, combining that with the possibility of per-query lookups of cross-type comparison functions seems to require changes in the APIs of a lot of the pruning support functions, so it's too invasive to consider as part of this patch. A win would ensue only for complex partition key data types (e.g. arrays), so it may not be worth the trouble. David Rowley and Tom Lane Discussion: https://postgr.es/m/17850.1528755844@sss.pgh.pa.us
This commit is contained in:
@ -20,49 +20,57 @@
|
||||
|
||||
/*
|
||||
* PartitionPruneContext
|
||||
* Stores information needed at runtime for pruning computations
|
||||
* related to a single partitioned table.
|
||||
*
|
||||
* Information about a partitioned table needed to perform partition pruning.
|
||||
* partrel Relcache pointer for the partitioned table,
|
||||
* if we have it open (else NULL).
|
||||
* strategy Partition strategy, e.g. LIST, RANGE, HASH.
|
||||
* partnatts Number of columns in the partition key.
|
||||
* nparts Number of partitions in this partitioned table.
|
||||
* boundinfo Partition boundary info for the partitioned table.
|
||||
* partcollation Array of partnatts elements, storing the collations of the
|
||||
* partition key columns.
|
||||
* partsupfunc Array of FmgrInfos for the comparison or hashing functions
|
||||
* associated with the partition keys (partnatts elements).
|
||||
* (This points into the partrel's partition key, typically.)
|
||||
* stepcmpfuncs Array of FmgrInfos for the comparison or hashing function
|
||||
* for each pruning step and partition key.
|
||||
* ppccontext Memory context holding this PartitionPruneContext's
|
||||
* subsidiary data, such as the FmgrInfos.
|
||||
* planstate Points to the parent plan node's PlanState when called
|
||||
* during execution; NULL when called from the planner.
|
||||
* exprstates Array of ExprStates, indexed as per PruneCtxStateIdx; one
|
||||
* for each partition key in each pruning step. Allocated if
|
||||
* planstate is non-NULL, otherwise NULL.
|
||||
* exprhasexecparam Array of bools, each true if corresponding 'exprstate'
|
||||
* expression contains any PARAM_EXEC Params. (Can be NULL
|
||||
* if planstate is NULL.)
|
||||
* evalexecparams True if it's safe to evaluate PARAM_EXEC Params.
|
||||
*/
|
||||
typedef struct PartitionPruneContext
|
||||
{
|
||||
/* Partition key information */
|
||||
Relation partrel;
|
||||
char strategy;
|
||||
int partnatts;
|
||||
Oid *partopfamily;
|
||||
Oid *partopcintype;
|
||||
int nparts;
|
||||
PartitionBoundInfo boundinfo;
|
||||
Oid *partcollation;
|
||||
FmgrInfo *partsupfunc;
|
||||
|
||||
/* Number of partitions */
|
||||
int nparts;
|
||||
|
||||
/* Partition boundary info */
|
||||
PartitionBoundInfo boundinfo;
|
||||
|
||||
/*
|
||||
* This will be set when the context is used from the executor, to allow
|
||||
* Params to be evaluated.
|
||||
*/
|
||||
FmgrInfo *stepcmpfuncs;
|
||||
MemoryContext ppccontext;
|
||||
PlanState *planstate;
|
||||
|
||||
/*
|
||||
* Array of ExprStates, indexed as per PruneCtxStateIdx; one for each
|
||||
* partkey in each pruning step. Allocated if planstate is non-NULL,
|
||||
* otherwise NULL.
|
||||
*/
|
||||
ExprState **exprstates;
|
||||
|
||||
/*
|
||||
* Similar array of flags, each true if corresponding 'exprstate'
|
||||
* expression contains any PARAM_EXEC Params. (Can be NULL if planstate
|
||||
* is NULL.)
|
||||
*/
|
||||
bool *exprhasexecparam;
|
||||
|
||||
/* true if it's safe to evaluate PARAM_EXEC Params */
|
||||
bool evalexecparams;
|
||||
} PartitionPruneContext;
|
||||
|
||||
/*
|
||||
* PruneCxtStateIdx() computes the correct index into the stepcmpfuncs[],
|
||||
* exprstates[] and exprhasexecparam[] arrays for step step_id and
|
||||
* partition key column keyno. (Note: there is code that assumes the
|
||||
* entries for a given step are sequential, so this is not chosen freely.)
|
||||
*/
|
||||
#define PruneCxtStateIdx(partnatts, step_id, keyno) \
|
||||
((partnatts) * (step_id) + (keyno))
|
||||
|
||||
|
Reference in New Issue
Block a user