Skip to content

Commit b6e44e2

Browse files
author
Rafa de la Torre
committed
Deparse Row Expression as subquery
A row expression cannot be deparsed as ROW(...) cause otherwise column names are lost when sending the deparsed query to the remote. RowExpr may be present in the planner tree, as the optimizer may "pull up" aggregation subqueries and it certainly does. In particular, ST_AsMVT may produce different results or may miss the geom column if column names are generated as f1, f2, ..., fn. This solves that issue by deparsing the row expression as an alias and embedding it into a subquery. This is the intended syntax transformation in pseudo-code: SELECT row_expr FROM from_clause WHERE where_caluse => SELECT alias FROM ( SELECT row_expr_fields FROM from_clause WHERE where_clause ) alias
1 parent f3a7fea commit b6e44e2

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

contrib/postgres_fdw/deparse.c

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ typedef struct deparse_expr_cxt
103103
* a base relation. */
104104
StringInfo buf; /* output buffer to append to */
105105
List **params_list; /* exprs that will become remote Params */
106+
RowExpr *row_expr; /* used for later generation of equivalent subquery */
106107
} deparse_expr_cxt;
107108

108109
#define REL_ALIAS_PREFIX "r"
@@ -1006,6 +1007,7 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel,
10061007
context.foreignrel = rel;
10071008
context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
10081009
context.params_list = params_list;
1010+
context.row_expr = NULL;
10091011

10101012
/* Construct SELECT clause */
10111013
deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
@@ -1132,6 +1134,26 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context)
11321134

11331135
/* Construct FROM clause */
11341136
appendStringInfoString(buf, " FROM ");
1137+
1138+
// We have a row expression. Add the corresponding subquery
1139+
if (context->row_expr) {
1140+
bool first;
1141+
ListCell *lc;
1142+
RowExpr *node = context->row_expr;
1143+
1144+
appendStringInfoString(buf, "(SELECT ");
1145+
first = true;
1146+
foreach(lc, node->args)
1147+
{
1148+
if (!first)
1149+
appendStringInfo(buf, ", ");
1150+
deparseExpr((Expr *) lfirst(lc), context);
1151+
first = false;
1152+
}
1153+
1154+
appendStringInfoString(buf, " FROM ");
1155+
}
1156+
11351157
deparseFromExprForRel(buf, context->root, scanrel,
11361158
(bms_num_members(scanrel->relids) > 1),
11371159
(Index) 0, NULL, context->params_list);
@@ -1142,6 +1164,12 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context)
11421164
appendStringInfoString(buf, " WHERE ");
11431165
appendConditions(quals, context);
11441166
}
1167+
1168+
// Close subquery and add an alias
1169+
if (context->row_expr) {
1170+
appendStringInfoString(buf, ") myalias");
1171+
context->row_expr = NULL;
1172+
}
11451173
}
11461174

11471175
/*
@@ -2376,19 +2404,12 @@ static void
23762404
deparseRowExpr(RowExpr *node, deparse_expr_cxt *context)
23772405
{
23782406
StringInfo buf = context->buf;
2379-
bool first;
2380-
ListCell *lc;
23812407

2382-
appendStringInfoString(buf, "ROW(");
2383-
first = true;
2384-
foreach(lc, node->args)
2385-
{
2386-
if (!first)
2387-
appendStringInfo(buf, ", ");
2388-
deparseExpr((Expr *) lfirst(lc), context);
2389-
first = false;
2390-
}
2391-
appendStringInfoChar(buf, ')');
2408+
// Add an arbitrary alias
2409+
appendStringInfoString(buf, "myalias");
2410+
2411+
// Just save the node for later generation of subquery
2412+
context->row_expr = node;
23922413
}
23932414

23942415
/*

0 commit comments

Comments
 (0)