Skip to content

Commit 642d0bd

Browse files
committed
replace extern params with consts via eval_extern_params_mutator()
1 parent 3a90ad9 commit 642d0bd

File tree

3 files changed

+72
-8
lines changed

3 files changed

+72
-8
lines changed

src/hooks.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
562562
incr_refcount_relation_tags();
563563

564564
/* Modify query tree if needed */
565-
pathman_transform_query(parse);
565+
pathman_transform_query(parse, boundParams);
566566
}
567567

568568
/* Invoke original hook if needed */
@@ -682,7 +682,7 @@ pathman_post_parse_analysis_hook(ParseState *pstate, Query *query)
682682
}
683683

684684
/* Modify query tree if needed */
685-
pathman_transform_query(query);
685+
pathman_transform_query(query, NULL);
686686
}
687687
}
688688

src/include/planner_tree_modification.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void plan_tree_walker(Plan *plan,
3030
void *context);
3131

3232
/* Query tree rewriting utility */
33-
void pathman_transform_query(Query *parse);
33+
void pathman_transform_query(Query *parse, ParamListInfo params);
3434

3535
/* These functions scribble on Plan tree */
3636
void add_partition_filters(List *rtable, Plan *plan);

src/planner_tree_modification.c

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
static bool pathman_transform_query_walker(Node *node, void *context);
3131

3232
static void disable_standard_inheritance(Query *parse);
33-
static void handle_modification_query(Query *parse);
33+
static void handle_modification_query(Query *parse, ParamListInfo params);
3434

3535
static void partition_filter_visitor(Plan *plan, void *context);
3636

3737
static rel_parenthood_status tag_extract_parenthood_status(List *relation_tag);
3838

39+
static Node *eval_extern_params_mutator(Node *node, ParamListInfo params);
40+
3941

4042
/*
4143
* HACK: We have to mark each Query with a unique
@@ -134,9 +136,9 @@ plan_tree_walker(Plan *plan,
134136

135137
/* Perform some transformations on Query tree */
136138
void
137-
pathman_transform_query(Query *parse)
139+
pathman_transform_query(Query *parse, ParamListInfo params)
138140
{
139-
pathman_transform_query_walker((Node *) parse, NULL);
141+
pathman_transform_query_walker((Node *) parse, (void *) params);
140142
}
141143

142144
/* Walker for pathman_transform_query() */
@@ -156,7 +158,7 @@ pathman_transform_query_walker(Node *node, void *context)
156158
/* Apply Query tree modifiers */
157159
rowmark_add_tableoids(query);
158160
disable_standard_inheritance(query);
159-
handle_modification_query(query);
161+
handle_modification_query(query, (ParamListInfo) context);
160162

161163
/* Handle Query node */
162164
return query_tree_walker(query,
@@ -236,7 +238,7 @@ disable_standard_inheritance(Query *parse)
236238

237239
/* Checks if query affects only one partition */
238240
static void
239-
handle_modification_query(Query *parse)
241+
handle_modification_query(Query *parse, ParamListInfo params)
240242
{
241243
const PartRelationInfo *prel;
242244
Node *prel_expr;
@@ -276,6 +278,10 @@ handle_modification_query(Query *parse)
276278
/* Exit if there's no expr (no use) */
277279
if (!expr) return;
278280

281+
/* Check if we can replace PARAMs with CONSTs */
282+
if (clause_contains_params((Node *) expr) && params)
283+
expr = (Expr *) eval_extern_params_mutator((Node *) expr, params);
284+
279285
/* Prepare partitioning expression */
280286
prel_expr = PrelExpressionForRelid(prel, result_rel);
281287

@@ -477,3 +483,61 @@ tag_extract_parenthood_status(List *relation_tag)
477483

478484
return status;
479485
}
486+
487+
488+
/* Replace extern param nodes with consts */
489+
static Node *
490+
eval_extern_params_mutator(Node *node, ParamListInfo params)
491+
{
492+
if (node == NULL)
493+
return NULL;
494+
495+
if (IsA(node, Param))
496+
{
497+
Param *param = (Param *) node;
498+
499+
/* Look to see if we've been given a value for this Param */
500+
if (param->paramkind == PARAM_EXTERN &&
501+
params != NULL &&
502+
param->paramid > 0 &&
503+
param->paramid <= params->numParams)
504+
{
505+
ParamExternData *prm = &params->params[param->paramid - 1];
506+
507+
if (OidIsValid(prm->ptype))
508+
{
509+
/* OK to substitute parameter value? */
510+
if (prm->pflags & PARAM_FLAG_CONST)
511+
{
512+
/*
513+
* Return a Const representing the param value.
514+
* Must copy pass-by-ref datatypes, since the
515+
* Param might be in a memory context
516+
* shorter-lived than our output plan should be.
517+
*/
518+
int16 typLen;
519+
bool typByVal;
520+
Datum pval;
521+
522+
Assert(prm->ptype == param->paramtype);
523+
get_typlenbyval(param->paramtype,
524+
&typLen, &typByVal);
525+
if (prm->isnull || typByVal)
526+
pval = prm->value;
527+
else
528+
pval = datumCopy(prm->value, typByVal, typLen);
529+
return (Node *) makeConst(param->paramtype,
530+
param->paramtypmod,
531+
param->paramcollid,
532+
(int) typLen,
533+
pval,
534+
prm->isnull,
535+
typByVal);
536+
}
537+
}
538+
}
539+
}
540+
541+
return expression_tree_mutator(node, eval_extern_params_mutator,
542+
(void *) params);
543+
}

0 commit comments

Comments
 (0)