Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7686403

Browse files
committed
Show 'AS "?column?"' explicitly when it's important.
ruleutils.c was coded to suppress the AS label for a SELECT output expression if the column name is "?column?", which is the parser's fallback if it can't think of something better. This is fine, and avoids ugly clutter, so long as (1) nothing further up in the parse tree relies on that column name or (2) the same fallback would be assigned when the rule or view definition is reloaded. Unfortunately (2) is far from certain, both because ruleutils.c might print the expression in a different form from how it was originally written and because FigureColname's rules might change in future releases. So we shouldn't rely on that. Detecting exactly whether there is any outer-level use of a SELECT column name would be rather expensive. This patch takes the simpler approach of just passing down a flag indicating whether there *could* be any outer use; for example, the output column names of a SubLink are not referenceable, and we also do not care about the names exposed by the right-hand side of a setop. This is sufficient to suppress unwanted clutter in all but one case in the regression tests. That seems like reasonable evidence that it won't be too much in users' faces, while still fixing the cases we need to fix. Per bug #17486 from Nicolas Lutic. This issue is ancient, so back-patch to all supported branches. Discussion: https://postgr.es/m/[email protected]
1 parent fc428fe commit 7686403

File tree

2 files changed

+66
-38
lines changed

2 files changed

+66
-38
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -370,26 +370,29 @@ static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
370370
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
371371
int prettyFlags, int wrapColumn);
372372
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
373-
TupleDesc resultDesc,
373+
TupleDesc resultDesc, bool colNamesVisible,
374374
int prettyFlags, int wrapColumn, int startIndent);
375375
static void get_values_def(List *values_lists, deparse_context *context);
376376
static void get_with_clause(Query *query, deparse_context *context);
377377
static void get_select_query_def(Query *query, deparse_context *context,
378-
TupleDesc resultDesc);
379-
static void get_insert_query_def(Query *query, deparse_context *context);
380-
static void get_update_query_def(Query *query, deparse_context *context);
378+
TupleDesc resultDesc, bool colNamesVisible);
379+
static void get_insert_query_def(Query *query, deparse_context *context,
380+
bool colNamesVisible);
381+
static void get_update_query_def(Query *query, deparse_context *context,
382+
bool colNamesVisible);
381383
static void get_update_query_targetlist_def(Query *query, List *targetList,
382384
deparse_context *context,
383385
RangeTblEntry *rte);
384-
static void get_delete_query_def(Query *query, deparse_context *context);
386+
static void get_delete_query_def(Query *query, deparse_context *context,
387+
bool colNamesVisible);
385388
static void get_utility_query_def(Query *query, deparse_context *context);
386389
static void get_basic_select_query(Query *query, deparse_context *context,
387-
TupleDesc resultDesc);
390+
TupleDesc resultDesc, bool colNamesVisible);
388391
static void get_target_list(List *targetList, deparse_context *context,
389-
TupleDesc resultDesc);
392+
TupleDesc resultDesc, bool colNamesVisible);
390393
static void get_setop_query(Node *setOp, Query *query,
391394
deparse_context *context,
392-
TupleDesc resultDesc);
395+
TupleDesc resultDesc, bool colNamesVisible);
393396
static Node *get_rule_sortgroupclause(Index ref, List *tlist,
394397
bool force_colno,
395398
deparse_context *context);
@@ -4788,7 +4791,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
47884791
foreach(action, actions)
47894792
{
47904793
query = (Query *) lfirst(action);
4791-
get_query_def(query, buf, NIL, viewResultDesc,
4794+
get_query_def(query, buf, NIL, viewResultDesc, true,
47924795
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
47934796
if (prettyFlags)
47944797
appendStringInfoString(buf, ";\n");
@@ -4806,7 +4809,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
48064809
Query *query;
48074810

48084811
query = (Query *) linitial(actions);
4809-
get_query_def(query, buf, NIL, viewResultDesc,
4812+
get_query_def(query, buf, NIL, viewResultDesc, true,
48104813
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
48114814
appendStringInfoChar(buf, ';');
48124815
}
@@ -4880,7 +4883,7 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
48804883

48814884
ev_relation = heap_open(ev_class, AccessShareLock);
48824885

4883-
get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
4886+
get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), true,
48844887
prettyFlags, wrapColumn, 0);
48854888
appendStringInfoChar(buf, ';');
48864889

@@ -4891,13 +4894,23 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
48914894
/* ----------
48924895
* get_query_def - Parse back one query parsetree
48934896
*
4894-
* If resultDesc is not NULL, then it is the output tuple descriptor for
4895-
* the view represented by a SELECT query.
4897+
* query: parsetree to be displayed
4898+
* buf: output text is appended to buf
4899+
* parentnamespace: list (initially empty) of outer-level deparse_namespace's
4900+
* resultDesc: if not NULL, the output tuple descriptor for the view
4901+
* represented by a SELECT query. We use the column names from it
4902+
* to label SELECT output columns, in preference to names in the query
4903+
* colNamesVisible: true if the surrounding context cares about the output
4904+
* column names at all (as, for example, an EXISTS() context does not);
4905+
* when false, we can suppress dummy column labels such as "?column?"
4906+
* prettyFlags: bitmask of PRETTYFLAG_XXX options
4907+
* wrapColumn: maximum line length, or -1 to disable wrapping
4908+
* startIndent: initial indentation amount
48964909
* ----------
48974910
*/
48984911
static void
48994912
get_query_def(Query *query, StringInfo buf, List *parentnamespace,
4900-
TupleDesc resultDesc,
4913+
TupleDesc resultDesc, bool colNamesVisible,
49014914
int prettyFlags, int wrapColumn, int startIndent)
49024915
{
49034916
deparse_context context;
@@ -4934,19 +4947,19 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace,
49344947
switch (query->commandType)
49354948
{
49364949
case CMD_SELECT:
4937-
get_select_query_def(query, &context, resultDesc);
4950+
get_select_query_def(query, &context, resultDesc, colNamesVisible);
49384951
break;
49394952

49404953
case CMD_UPDATE:
4941-
get_update_query_def(query, &context);
4954+
get_update_query_def(query, &context, colNamesVisible);
49424955
break;
49434956

49444957
case CMD_INSERT:
4945-
get_insert_query_def(query, &context);
4958+
get_insert_query_def(query, &context, colNamesVisible);
49464959
break;
49474960

49484961
case CMD_DELETE:
4949-
get_delete_query_def(query, &context);
4962+
get_delete_query_def(query, &context, colNamesVisible);
49504963
break;
49514964

49524965
case CMD_NOTHING:
@@ -5058,6 +5071,7 @@ get_with_clause(Query *query, deparse_context *context)
50585071
if (PRETTY_INDENT(context))
50595072
appendContextKeyword(context, "", 0, 0, 0);
50605073
get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
5074+
true,
50615075
context->prettyFlags, context->wrapColumn,
50625076
context->indentLevel);
50635077
if (PRETTY_INDENT(context))
@@ -5081,7 +5095,7 @@ get_with_clause(Query *query, deparse_context *context)
50815095
*/
50825096
static void
50835097
get_select_query_def(Query *query, deparse_context *context,
5084-
TupleDesc resultDesc)
5098+
TupleDesc resultDesc, bool colNamesVisible)
50855099
{
50865100
StringInfo buf = context->buf;
50875101
List *save_windowclause;
@@ -5105,13 +5119,14 @@ get_select_query_def(Query *query, deparse_context *context,
51055119
*/
51065120
if (query->setOperations)
51075121
{
5108-
get_setop_query(query->setOperations, query, context, resultDesc);
5122+
get_setop_query(query->setOperations, query, context, resultDesc,
5123+
colNamesVisible);
51095124
/* ORDER BY clauses must be simple in this case */
51105125
force_colno = true;
51115126
}
51125127
else
51135128
{
5114-
get_basic_select_query(query, context, resultDesc);
5129+
get_basic_select_query(query, context, resultDesc, colNamesVisible);
51155130
force_colno = false;
51165131
}
51175132

@@ -5268,7 +5283,7 @@ get_simple_values_rte(Query *query, TupleDesc resultDesc)
52685283

52695284
static void
52705285
get_basic_select_query(Query *query, deparse_context *context,
5271-
TupleDesc resultDesc)
5286+
TupleDesc resultDesc, bool colNamesVisible)
52725287
{
52735288
StringInfo buf = context->buf;
52745289
RangeTblEntry *values_rte;
@@ -5321,7 +5336,7 @@ get_basic_select_query(Query *query, deparse_context *context,
53215336
}
53225337

53235338
/* Then we tell what to select (the targetlist) */
5324-
get_target_list(query->targetList, context, resultDesc);
5339+
get_target_list(query->targetList, context, resultDesc, colNamesVisible);
53255340

53265341
/* Add the FROM clause if needed */
53275342
get_from_clause(query, " FROM ", context);
@@ -5391,11 +5406,13 @@ get_basic_select_query(Query *query, deparse_context *context,
53915406
* get_target_list - Parse back a SELECT target list
53925407
*
53935408
* This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
5409+
*
5410+
* resultDesc and colNamesVisible are as for get_query_def()
53945411
* ----------
53955412
*/
53965413
static void
53975414
get_target_list(List *targetList, deparse_context *context,
5398-
TupleDesc resultDesc)
5415+
TupleDesc resultDesc, bool colNamesVisible)
53995416
{
54005417
StringInfo buf = context->buf;
54015418
StringInfoData targetbuf;
@@ -5446,8 +5463,13 @@ get_target_list(List *targetList, deparse_context *context,
54465463
else
54475464
{
54485465
get_rule_expr((Node *) tle->expr, context, true);
5449-
/* We'll show the AS name unless it's this: */
5450-
attname = "?column?";
5466+
5467+
/*
5468+
* When colNamesVisible is true, we should always show the
5469+
* assigned column name explicitly. Otherwise, show it only if
5470+
* it's not FigureColname's fallback.
5471+
*/
5472+
attname = colNamesVisible ? NULL : "?column?";
54515473
}
54525474

54535475
/*
@@ -5526,7 +5548,7 @@ get_target_list(List *targetList, deparse_context *context,
55265548

55275549
static void
55285550
get_setop_query(Node *setOp, Query *query, deparse_context *context,
5529-
TupleDesc resultDesc)
5551+
TupleDesc resultDesc, bool colNamesVisible)
55305552
{
55315553
StringInfo buf = context->buf;
55325554
bool need_paren;
@@ -5552,6 +5574,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
55525574
if (need_paren)
55535575
appendStringInfoChar(buf, '(');
55545576
get_query_def(subquery, buf, context->namespaces, resultDesc,
5577+
colNamesVisible,
55555578
context->prettyFlags, context->wrapColumn,
55565579
context->indentLevel);
55575580
if (need_paren)
@@ -5594,7 +5617,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
55945617
else
55955618
subindent = 0;
55965619

5597-
get_setop_query(op->larg, query, context, resultDesc);
5620+
get_setop_query(op->larg, query, context, resultDesc, colNamesVisible);
55985621

55995622
if (need_paren)
56005623
appendContextKeyword(context, ") ", -subindent, 0, 0);
@@ -5638,7 +5661,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
56385661
subindent = 0;
56395662
appendContextKeyword(context, "", subindent, 0, 0);
56405663

5641-
get_setop_query(op->rarg, query, context, resultDesc);
5664+
get_setop_query(op->rarg, query, context, resultDesc, false);
56425665

56435666
if (PRETTY_INDENT(context))
56445667
context->indentLevel -= subindent;
@@ -5965,7 +5988,8 @@ get_rule_windowspec(WindowClause *wc, List *targetList,
59655988
* ----------
59665989
*/
59675990
static void
5968-
get_insert_query_def(Query *query, deparse_context *context)
5991+
get_insert_query_def(Query *query, deparse_context *context,
5992+
bool colNamesVisible)
59695993
{
59705994
StringInfo buf = context->buf;
59715995
RangeTblEntry *select_rte = NULL;
@@ -6074,6 +6098,7 @@ get_insert_query_def(Query *query, deparse_context *context)
60746098
{
60756099
/* Add the SELECT */
60766100
get_query_def(select_rte->subquery, buf, NIL, NULL,
6101+
false,
60776102
context->prettyFlags, context->wrapColumn,
60786103
context->indentLevel);
60796104
}
@@ -6167,7 +6192,7 @@ get_insert_query_def(Query *query, deparse_context *context)
61676192
{
61686193
appendContextKeyword(context, " RETURNING",
61696194
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6170-
get_target_list(query->returningList, context, NULL);
6195+
get_target_list(query->returningList, context, NULL, colNamesVisible);
61716196
}
61726197
}
61736198

@@ -6177,7 +6202,8 @@ get_insert_query_def(Query *query, deparse_context *context)
61776202
* ----------
61786203
*/
61796204
static void
6180-
get_update_query_def(Query *query, deparse_context *context)
6205+
get_update_query_def(Query *query, deparse_context *context,
6206+
bool colNamesVisible)
61816207
{
61826208
StringInfo buf = context->buf;
61836209
RangeTblEntry *rte;
@@ -6222,7 +6248,7 @@ get_update_query_def(Query *query, deparse_context *context)
62226248
{
62236249
appendContextKeyword(context, " RETURNING",
62246250
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6225-
get_target_list(query->returningList, context, NULL);
6251+
get_target_list(query->returningList, context, NULL, colNamesVisible);
62266252
}
62276253
}
62286254

@@ -6383,7 +6409,8 @@ get_update_query_targetlist_def(Query *query, List *targetList,
63836409
* ----------
63846410
*/
63856411
static void
6386-
get_delete_query_def(Query *query, deparse_context *context)
6412+
get_delete_query_def(Query *query, deparse_context *context,
6413+
bool colNamesVisible)
63876414
{
63886415
StringInfo buf = context->buf;
63896416
RangeTblEntry *rte;
@@ -6424,7 +6451,7 @@ get_delete_query_def(Query *query, deparse_context *context)
64246451
{
64256452
appendContextKeyword(context, " RETURNING",
64266453
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6427-
get_target_list(query->returningList, context, NULL);
6454+
get_target_list(query->returningList, context, NULL, colNamesVisible);
64286455
}
64296456
}
64306457

@@ -9624,7 +9651,7 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
96249651
if (need_paren)
96259652
appendStringInfoChar(buf, '(');
96269653

9627-
get_query_def(query, buf, context->namespaces, NULL,
9654+
get_query_def(query, buf, context->namespaces, NULL, false,
96289655
context->prettyFlags, context->wrapColumn,
96299656
context->indentLevel);
96309657

@@ -9883,6 +9910,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
98839910
/* Subquery RTE */
98849911
appendStringInfoChar(buf, '(');
98859912
get_query_def(rte->subquery, buf, context->namespaces, NULL,
9913+
true,
98869914
context->prettyFlags, context->wrapColumn,
98879915
context->indentLevel);
98889916
appendStringInfoChar(buf, ')');

src/test/regress/expected/matview.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ CREATE VIEW mvtest_vt2 AS SELECT moo, 2*moo FROM mvtest_vt1 UNION ALL SELECT moo
347347
?column? | integer | | | | plain |
348348
View definition:
349349
SELECT mvtest_vt1.moo,
350-
2 * mvtest_vt1.moo
350+
2 * mvtest_vt1.moo AS "?column?"
351351
FROM mvtest_vt1
352352
UNION ALL
353353
SELECT mvtest_vt1.moo,
@@ -363,7 +363,7 @@ CREATE MATERIALIZED VIEW mv_test2 AS SELECT moo, 2*moo FROM mvtest_vt2 UNION ALL
363363
?column? | integer | | | | plain | |
364364
View definition:
365365
SELECT mvtest_vt2.moo,
366-
2 * mvtest_vt2.moo
366+
2 * mvtest_vt2.moo AS "?column?"
367367
FROM mvtest_vt2
368368
UNION ALL
369369
SELECT mvtest_vt2.moo,

0 commit comments

Comments
 (0)