Add OLD/NEW support to RETURNING in DML queries.

80feb727c869cc0b2e12bd1543bafa449be9c8e2
m3hm3t/pg18_dev_relation_oid_0
Mehmet Yilmaz 2025-05-30 09:12:12 +00:00
parent 3dccc99d70
commit 85ffb3ff7d
1 changed files with 75 additions and 11 deletions

View File

@ -172,6 +172,8 @@ typedef struct
List *subplans; /* List of Plan trees for SubPlans */ List *subplans; /* List of Plan trees for SubPlans */
List *ctes; /* List of CommonTableExpr nodes */ List *ctes; /* List of CommonTableExpr nodes */
AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */ AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
char *ret_old_alias; /* alias for OLD in RETURNING list */
char *ret_new_alias; /* alias for NEW in RETURNING list */
/* Workspace for column alias assignment: */ /* Workspace for column alias assignment: */
bool unique_using; /* Are we making USING names globally unique */ bool unique_using; /* Are we making USING names globally unique */
List *using_names; /* List of assigned names for USING columns */ List *using_names; /* List of assigned names for USING columns */
@ -375,6 +377,7 @@ static void get_merge_query_def(Query *query, deparse_context *context);
static void get_utility_query_def(Query *query, deparse_context *context); static void get_utility_query_def(Query *query, deparse_context *context);
static void get_basic_select_query(Query *query, deparse_context *context); static void get_basic_select_query(Query *query, deparse_context *context);
static void get_target_list(List *targetList, deparse_context *context); static void get_target_list(List *targetList, deparse_context *context);
static void get_returning_clause(Query *query, deparse_context *context);
static void get_setop_query(Node *setOp, Query *query, static void get_setop_query(Node *setOp, Query *query,
deparse_context *context); deparse_context *context);
static Node *get_rule_sortgroupclause(Index ref, List *tlist, static Node *get_rule_sortgroupclause(Index ref, List *tlist,
@ -852,6 +855,8 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query,
dpns->subplans = NIL; dpns->subplans = NIL;
dpns->ctes = query->cteList; dpns->ctes = query->cteList;
dpns->appendrels = NULL; dpns->appendrels = NULL;
dpns->ret_old_alias = query->returningOldAlias;
dpns->ret_new_alias = query->returningNewAlias;
/* Assign a unique relation alias to each RTE */ /* Assign a unique relation alias to each RTE */
set_rtable_names(dpns, parent_namespaces, NULL); set_rtable_names(dpns, parent_namespaces, NULL);
@ -2795,6 +2800,45 @@ get_target_list(List *targetList, deparse_context *context)
pfree(targetbuf.data); pfree(targetbuf.data);
} }
static void
get_returning_clause(Query *query, deparse_context *context)
{
StringInfo buf = context->buf;
if (query->returningList)
{
bool have_with = false;
appendContextKeyword(context, " RETURNING",
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
/* Add WITH (OLD/NEW) options, if they're not the defaults */
if (query->returningOldAlias && strcmp(query->returningOldAlias, "old") != 0)
{
appendStringInfo(buf, " WITH (OLD AS %s",
quote_identifier(query->returningOldAlias));
have_with = true;
}
if (query->returningNewAlias && strcmp(query->returningNewAlias, "new") != 0)
{
if (have_with)
appendStringInfo(buf, ", NEW AS %s",
quote_identifier(query->returningNewAlias));
else
{
appendStringInfo(buf, " WITH (NEW AS %s",
quote_identifier(query->returningNewAlias));
have_with = true;
}
}
if (have_with)
appendStringInfoChar(buf, ')');
/* Add the returning expressions themselves */
get_target_list(query->returningList, context);
}
}
static void static void
get_setop_query(Node *setOp, Query *query, deparse_context *context) get_setop_query(Node *setOp, Query *query, deparse_context *context)
{ {
@ -3447,9 +3491,7 @@ get_insert_query_def(Query *query, deparse_context *context)
/* Add RETURNING if present */ /* Add RETURNING if present */
if (query->returningList) if (query->returningList)
{ {
appendContextKeyword(context, " RETURNING", get_returning_clause(query, context);
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
get_target_list(query->returningList, context);
} }
} }
@ -3525,9 +3567,7 @@ get_update_query_def(Query *query, deparse_context *context)
/* Add RETURNING if present */ /* Add RETURNING if present */
if (query->returningList) if (query->returningList)
{ {
appendContextKeyword(context, " RETURNING", get_returning_clause(query, context);
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
get_target_list(query->returningList, context);
} }
} }
@ -3749,9 +3789,7 @@ get_delete_query_def(Query *query, deparse_context *context)
/* Add RETURNING if present */ /* Add RETURNING if present */
if (query->returningList) if (query->returningList)
{ {
appendContextKeyword(context, " RETURNING", get_returning_clause(query, context);
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
get_target_list(query->returningList, context);
} }
} }
@ -4125,7 +4163,15 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
} }
rte = rt_fetch(varno, dpns->rtable); rte = rt_fetch(varno, dpns->rtable);
refname = (char *) list_nth(dpns->rtable_names, varno - 1);
/* might be returning old/new column value */
if (var->varreturningtype == VAR_RETURNING_OLD)
refname = dpns->ret_old_alias;
else if (var->varreturningtype == VAR_RETURNING_NEW)
refname = dpns->ret_new_alias;
else
refname = (char *) list_nth(dpns->rtable_names, varno - 1);
colinfo = deparse_columns_fetch(varno, dpns); colinfo = deparse_columns_fetch(varno, dpns);
attnum = varattno; attnum = varattno;
} }
@ -4244,7 +4290,8 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
attname = get_rte_attribute_name(rte, attnum); attname = get_rte_attribute_name(rte, attnum);
} }
need_prefix = (context->varprefix || attname == NULL); need_prefix = (context->varprefix || attname == NULL ||
var->varreturningtype != VAR_RETURNING_DEFAULT);
/* /*
* If we're considering a plain Var in an ORDER BY (but not GROUP BY) * If we're considering a plain Var in an ORDER BY (but not GROUP BY)
* clause, we may need to add a table-name prefix to prevent * clause, we may need to add a table-name prefix to prevent
@ -5342,6 +5389,9 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_ConvertRowtypeExpr: case T_ConvertRowtypeExpr:
return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg, return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
node, prettyFlags); node, prettyFlags);
case T_ReturningExpr:
return isSimpleNode((Node *) ((ReturningExpr *) node)->retexpr,
node, prettyFlags);
case T_OpExpr: case T_OpExpr:
{ {
@ -6824,6 +6874,20 @@ get_rule_expr(Node *node, deparse_context *context,
} }
} }
break; break;
case T_ReturningExpr:
{
ReturningExpr *retExpr = (ReturningExpr *) node;
/*
* We cannot see a ReturningExpr in rule deparsing, only while
* EXPLAINing a query plan (ReturningExpr nodes are only ever
* adding during query rewriting). Just display the expression
* returned (an expanded view column).
*/
get_rule_expr((Node *) retExpr->retexpr, context, showimplicit);
}
break;
case T_PartitionBoundSpec: case T_PartitionBoundSpec:
{ {