diff options
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 24ade6cc201..bf4e81f554a 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -5493,6 +5493,26 @@ get_utility_query_def(Query *query, deparse_context *context) } } +/* + * GetSpecialCustomVar + * + * If a custom-scan provider uses a special varnode, this function will be + * called when deparsing; it should return an Expr node to be reversed-listed + * in lieu of the special Var. + */ +static Node * +GetSpecialCustomVar(CustomScanState *css, Var *varnode, PlanState **child_ps) +{ + Assert(IsA(css, CustomScanState)); + Assert(IS_SPECIAL_VARNO(varnode->varno)); + + if (!css->methods->GetSpecialCustomVar) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("%s does not support special varno reference", + css->methods->CustomName))); + return (Node *) css->methods->GetSpecialCustomVar(css, varnode, child_ps); +} /* * Display a Var appropriately. @@ -5522,6 +5542,8 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) int netlevelsup; deparse_namespace *dpns; deparse_columns *colinfo; + PlanState *child_ps = NULL; + Node *expr; char *refname; char *attname; @@ -5546,6 +5568,29 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) colinfo = deparse_columns_fetch(var->varno, dpns); attnum = var->varattno; } + else if (IS_SPECIAL_VARNO(var->varno) && + IsA(dpns->planstate, CustomScanState) && + (expr = GetSpecialCustomVar((CustomScanState *) dpns->planstate, + var, &child_ps)) != NULL) + { + deparse_namespace save_dpns; + + if (child_ps) + push_child_plan(dpns, child_ps, &save_dpns); + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) expr, context, true); + if (!IsA(expr, Var)) + appendStringInfoChar(buf, ')'); + + if (child_ps) + pop_child_plan(dpns, &save_dpns); + return NULL; + } else if (var->varno == OUTER_VAR && dpns->outer_tlist) { TargetEntry *tle; @@ -5760,6 +5805,7 @@ get_name_for_var_field(Var *var, int fieldno, AttrNumber attnum; int netlevelsup; deparse_namespace *dpns; + PlanState *child_ps = NULL; TupleDesc tupleDesc; Node *expr; @@ -5834,6 +5880,30 @@ get_name_for_var_field(Var *var, int fieldno, rte = rt_fetch(var->varno, dpns->rtable); attnum = var->varattno; } + else if (IS_SPECIAL_VARNO(var->varno) && + IsA(dpns->planstate, CustomScanState) && + (expr = GetSpecialCustomVar((CustomScanState *) dpns->planstate, + var, &child_ps)) != NULL) + { + StringInfo saved = context->buf; + StringInfoData temp; + deparse_namespace save_dpns; + + initStringInfo(&temp); + context->buf = &temp; + + if (child_ps) + push_child_plan(dpns, child_ps, &save_dpns); + if (!IsA(expr, Var)) + appendStringInfoChar(context->buf, '('); + get_rule_expr((Node *) expr, context, true); + if (!IsA(expr, Var)) + appendStringInfoChar(context->buf, ')'); + if (child_ps) + pop_child_plan(dpns, &save_dpns); + context->buf = saved; + return temp.data; + } else if (var->varno == OUTER_VAR && dpns->outer_tlist) { TargetEntry *tle; |