Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c7461fc

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/17486-1ad6fd786728b8af@postgresql.org
1 parent e19272e commit c7461fc

File tree

2 files changed

+70
-41
lines changed

2 files changed

+70
-41
lines changed

src/backend/utils/adt/ruleutils.c

+68-39
Original file line numberDiff line numberDiff line change
@@ -395,26 +395,29 @@ static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
395395
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
396396
int prettyFlags, int wrapColumn);
397397
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
398-
TupleDesc resultDesc,
398+
TupleDesc resultDesc, bool colNamesVisible,
399399
int prettyFlags, int wrapColumn, int startIndent);
400400
static void get_values_def(List *values_lists, deparse_context *context);
401401
static void get_with_clause(Query *query, deparse_context *context);
402402
static void get_select_query_def(Query *query, deparse_context *context,
403-
TupleDesc resultDesc);
404-
static void get_insert_query_def(Query *query, deparse_context *context);
405-
static void get_update_query_def(Query *query, deparse_context *context);
403+
TupleDesc resultDesc, bool colNamesVisible);
404+
static void get_insert_query_def(Query *query, deparse_context *context,
405+
bool colNamesVisible);
406+
static void get_update_query_def(Query *query, deparse_context *context,
407+
bool colNamesVisible);
406408
static void get_update_query_targetlist_def(Query *query, List *targetList,
407409
deparse_context *context,
408410
RangeTblEntry *rte);
409-
static void get_delete_query_def(Query *query, deparse_context *context);
411+
static void get_delete_query_def(Query *query, deparse_context *context,
412+
bool colNamesVisible);
410413
static void get_utility_query_def(Query *query, deparse_context *context);
411414
static void get_basic_select_query(Query *query, deparse_context *context,
412-
TupleDesc resultDesc);
415+
TupleDesc resultDesc, bool colNamesVisible);
413416
static void get_target_list(List *targetList, deparse_context *context,
414-
TupleDesc resultDesc);
417+
TupleDesc resultDesc, bool colNamesVisible);
415418
static void get_setop_query(Node *setOp, Query *query,
416419
deparse_context *context,
417-
TupleDesc resultDesc);
420+
TupleDesc resultDesc, bool colNamesVisible);
418421
static Node *get_rule_sortgroupclause(Index ref, List *tlist,
419422
bool force_colno,
420423
deparse_context *context);
@@ -1544,7 +1547,8 @@ pg_get_querydef(Query *query, bool pretty)
15441547

15451548
initStringInfo(&buf);
15461549

1547-
get_query_def(query, &buf, NIL, NULL, prettyFlags, WRAP_COLUMN_DEFAULT, 0);
1550+
get_query_def(query, &buf, NIL, NULL, true,
1551+
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
15481552

15491553
return buf.data;
15501554
}
@@ -3548,7 +3552,7 @@ print_function_sqlbody(StringInfo buf, HeapTuple proctup)
35483552

35493553
/* It seems advisable to get at least AccessShareLock on rels */
35503554
AcquireRewriteLocks(query, false, false);
3551-
get_query_def(query, buf, list_make1(&dpns), NULL,
3555+
get_query_def(query, buf, list_make1(&dpns), NULL, false,
35523556
PRETTYFLAG_INDENT, WRAP_COLUMN_DEFAULT, 1);
35533557
appendStringInfoChar(buf, ';');
35543558
appendStringInfoChar(buf, '\n');
@@ -3562,7 +3566,7 @@ print_function_sqlbody(StringInfo buf, HeapTuple proctup)
35623566

35633567
/* It seems advisable to get at least AccessShareLock on rels */
35643568
AcquireRewriteLocks(query, false, false);
3565-
get_query_def(query, buf, list_make1(&dpns), NULL,
3569+
get_query_def(query, buf, list_make1(&dpns), NULL, false,
35663570
0, WRAP_COLUMN_DEFAULT, 0);
35673571
}
35683572
}
@@ -5299,7 +5303,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
52995303
foreach(action, actions)
53005304
{
53015305
query = (Query *) lfirst(action);
5302-
get_query_def(query, buf, NIL, viewResultDesc,
5306+
get_query_def(query, buf, NIL, viewResultDesc, true,
53035307
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
53045308
if (prettyFlags)
53055309
appendStringInfoString(buf, ";\n");
@@ -5313,7 +5317,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
53135317
Query *query;
53145318

53155319
query = (Query *) linitial(actions);
5316-
get_query_def(query, buf, NIL, viewResultDesc,
5320+
get_query_def(query, buf, NIL, viewResultDesc, true,
53175321
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
53185322
appendStringInfoChar(buf, ';');
53195323
}
@@ -5387,7 +5391,7 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
53875391

53885392
ev_relation = table_open(ev_class, AccessShareLock);
53895393

5390-
get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
5394+
get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), true,
53915395
prettyFlags, wrapColumn, 0);
53925396
appendStringInfoChar(buf, ';');
53935397

@@ -5398,13 +5402,23 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
53985402
/* ----------
53995403
* get_query_def - Parse back one query parsetree
54005404
*
5401-
* If resultDesc is not NULL, then it is the output tuple descriptor for
5402-
* the view represented by a SELECT query.
5405+
* query: parsetree to be displayed
5406+
* buf: output text is appended to buf
5407+
* parentnamespace: list (initially empty) of outer-level deparse_namespace's
5408+
* resultDesc: if not NULL, the output tuple descriptor for the view
5409+
* represented by a SELECT query. We use the column names from it
5410+
* to label SELECT output columns, in preference to names in the query
5411+
* colNamesVisible: true if the surrounding context cares about the output
5412+
* column names at all (as, for example, an EXISTS() context does not);
5413+
* when false, we can suppress dummy column labels such as "?column?"
5414+
* prettyFlags: bitmask of PRETTYFLAG_XXX options
5415+
* wrapColumn: maximum line length, or -1 to disable wrapping
5416+
* startIndent: initial indentation amount
54035417
* ----------
54045418
*/
54055419
static void
54065420
get_query_def(Query *query, StringInfo buf, List *parentnamespace,
5407-
TupleDesc resultDesc,
5421+
TupleDesc resultDesc, bool colNamesVisible,
54085422
int prettyFlags, int wrapColumn, int startIndent)
54095423
{
54105424
deparse_context context;
@@ -5442,19 +5456,19 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace,
54425456
switch (query->commandType)
54435457
{
54445458
case CMD_SELECT:
5445-
get_select_query_def(query, &context, resultDesc);
5459+
get_select_query_def(query, &context, resultDesc, colNamesVisible);
54465460
break;
54475461

54485462
case CMD_UPDATE:
5449-
get_update_query_def(query, &context);
5463+
get_update_query_def(query, &context, colNamesVisible);
54505464
break;
54515465

54525466
case CMD_INSERT:
5453-
get_insert_query_def(query, &context);
5467+
get_insert_query_def(query, &context, colNamesVisible);
54545468
break;
54555469

54565470
case CMD_DELETE:
5457-
get_delete_query_def(query, &context);
5471+
get_delete_query_def(query, &context, colNamesVisible);
54585472
break;
54595473

54605474
case CMD_NOTHING:
@@ -5578,6 +5592,7 @@ get_with_clause(Query *query, deparse_context *context)
55785592
if (PRETTY_INDENT(context))
55795593
appendContextKeyword(context, "", 0, 0, 0);
55805594
get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
5595+
true,
55815596
context->prettyFlags, context->wrapColumn,
55825597
context->indentLevel);
55835598
if (PRETTY_INDENT(context))
@@ -5659,7 +5674,7 @@ get_with_clause(Query *query, deparse_context *context)
56595674
*/
56605675
static void
56615676
get_select_query_def(Query *query, deparse_context *context,
5662-
TupleDesc resultDesc)
5677+
TupleDesc resultDesc, bool colNamesVisible)
56635678
{
56645679
StringInfo buf = context->buf;
56655680
List *save_windowclause;
@@ -5683,13 +5698,14 @@ get_select_query_def(Query *query, deparse_context *context,
56835698
*/
56845699
if (query->setOperations)
56855700
{
5686-
get_setop_query(query->setOperations, query, context, resultDesc);
5701+
get_setop_query(query->setOperations, query, context, resultDesc,
5702+
colNamesVisible);
56875703
/* ORDER BY clauses must be simple in this case */
56885704
force_colno = true;
56895705
}
56905706
else
56915707
{
5692-
get_basic_select_query(query, context, resultDesc);
5708+
get_basic_select_query(query, context, resultDesc, colNamesVisible);
56935709
force_colno = false;
56945710
}
56955711

@@ -5859,7 +5875,7 @@ get_simple_values_rte(Query *query, TupleDesc resultDesc)
58595875

58605876
static void
58615877
get_basic_select_query(Query *query, deparse_context *context,
5862-
TupleDesc resultDesc)
5878+
TupleDesc resultDesc, bool colNamesVisible)
58635879
{
58645880
StringInfo buf = context->buf;
58655881
RangeTblEntry *values_rte;
@@ -5915,7 +5931,7 @@ get_basic_select_query(Query *query, deparse_context *context,
59155931
}
59165932

59175933
/* Then we tell what to select (the targetlist) */
5918-
get_target_list(query->targetList, context, resultDesc);
5934+
get_target_list(query->targetList, context, resultDesc, colNamesVisible);
59195935

59205936
/* Add the FROM clause if needed */
59215937
get_from_clause(query, " FROM ", context);
@@ -5987,11 +6003,13 @@ get_basic_select_query(Query *query, deparse_context *context,
59876003
* get_target_list - Parse back a SELECT target list
59886004
*
59896005
* This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
6006+
*
6007+
* resultDesc and colNamesVisible are as for get_query_def()
59906008
* ----------
59916009
*/
59926010
static void
59936011
get_target_list(List *targetList, deparse_context *context,
5994-
TupleDesc resultDesc)
6012+
TupleDesc resultDesc, bool colNamesVisible)
59956013
{
59966014
StringInfo buf = context->buf;
59976015
StringInfoData targetbuf;
@@ -6042,8 +6060,13 @@ get_target_list(List *targetList, deparse_context *context,
60426060
else
60436061
{
60446062
get_rule_expr((Node *) tle->expr, context, true);
6045-
/* We'll show the AS name unless it's this: */
6046-
attname = "?column?";
6063+
6064+
/*
6065+
* When colNamesVisible is true, we should always show the
6066+
* assigned column name explicitly. Otherwise, show it only if
6067+
* it's not FigureColname's fallback.
6068+
*/
6069+
attname = colNamesVisible ? NULL : "?column?";
60476070
}
60486071

60496072
/*
@@ -6122,7 +6145,7 @@ get_target_list(List *targetList, deparse_context *context,
61226145

61236146
static void
61246147
get_setop_query(Node *setOp, Query *query, deparse_context *context,
6125-
TupleDesc resultDesc)
6148+
TupleDesc resultDesc, bool colNamesVisible)
61266149
{
61276150
StringInfo buf = context->buf;
61286151
bool need_paren;
@@ -6148,6 +6171,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
61486171
if (need_paren)
61496172
appendStringInfoChar(buf, '(');
61506173
get_query_def(subquery, buf, context->namespaces, resultDesc,
6174+
colNamesVisible,
61516175
context->prettyFlags, context->wrapColumn,
61526176
context->indentLevel);
61536177
if (need_paren)
@@ -6190,7 +6214,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
61906214
else
61916215
subindent = 0;
61926216

6193-
get_setop_query(op->larg, query, context, resultDesc);
6217+
get_setop_query(op->larg, query, context, resultDesc, colNamesVisible);
61946218

61956219
if (need_paren)
61966220
appendContextKeyword(context, ") ", -subindent, 0, 0);
@@ -6234,7 +6258,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
62346258
subindent = 0;
62356259
appendContextKeyword(context, "", subindent, 0, 0);
62366260

6237-
get_setop_query(op->rarg, query, context, resultDesc);
6261+
get_setop_query(op->rarg, query, context, resultDesc, false);
62386262

62396263
if (PRETTY_INDENT(context))
62406264
context->indentLevel -= subindent;
@@ -6570,7 +6594,8 @@ get_rule_windowspec(WindowClause *wc, List *targetList,
65706594
* ----------
65716595
*/
65726596
static void
6573-
get_insert_query_def(Query *query, deparse_context *context)
6597+
get_insert_query_def(Query *query, deparse_context *context,
6598+
bool colNamesVisible)
65746599
{
65756600
StringInfo buf = context->buf;
65766601
RangeTblEntry *select_rte = NULL;
@@ -6680,6 +6705,7 @@ get_insert_query_def(Query *query, deparse_context *context)
66806705
{
66816706
/* Add the SELECT */
66826707
get_query_def(select_rte->subquery, buf, context->namespaces, NULL,
6708+
false,
66836709
context->prettyFlags, context->wrapColumn,
66846710
context->indentLevel);
66856711
}
@@ -6773,7 +6799,7 @@ get_insert_query_def(Query *query, deparse_context *context)
67736799
{
67746800
appendContextKeyword(context, " RETURNING",
67756801
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6776-
get_target_list(query->returningList, context, NULL);
6802+
get_target_list(query->returningList, context, NULL, colNamesVisible);
67776803
}
67786804
}
67796805

@@ -6783,7 +6809,8 @@ get_insert_query_def(Query *query, deparse_context *context)
67836809
* ----------
67846810
*/
67856811
static void
6786-
get_update_query_def(Query *query, deparse_context *context)
6812+
get_update_query_def(Query *query, deparse_context *context,
6813+
bool colNamesVisible)
67876814
{
67886815
StringInfo buf = context->buf;
67896816
RangeTblEntry *rte;
@@ -6828,7 +6855,7 @@ get_update_query_def(Query *query, deparse_context *context)
68286855
{
68296856
appendContextKeyword(context, " RETURNING",
68306857
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6831-
get_target_list(query->returningList, context, NULL);
6858+
get_target_list(query->returningList, context, NULL, colNamesVisible);
68326859
}
68336860
}
68346861

@@ -6990,7 +7017,8 @@ get_update_query_targetlist_def(Query *query, List *targetList,
69907017
* ----------
69917018
*/
69927019
static void
6993-
get_delete_query_def(Query *query, deparse_context *context)
7020+
get_delete_query_def(Query *query, deparse_context *context,
7021+
bool colNamesVisible)
69947022
{
69957023
StringInfo buf = context->buf;
69967024
RangeTblEntry *rte;
@@ -7031,7 +7059,7 @@ get_delete_query_def(Query *query, deparse_context *context)
70317059
{
70327060
appendContextKeyword(context, " RETURNING",
70337061
-PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
7034-
get_target_list(query->returningList, context, NULL);
7062+
get_target_list(query->returningList, context, NULL, colNamesVisible);
70357063
}
70367064
}
70377065

@@ -11039,7 +11067,7 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
1103911067
if (need_paren)
1104011068
appendStringInfoChar(buf, '(');
1104111069

11042-
get_query_def(query, buf, context->namespaces, NULL,
11070+
get_query_def(query, buf, context->namespaces, NULL, false,
1104311071
context->prettyFlags, context->wrapColumn,
1104411072
context->indentLevel);
1104511073

@@ -11548,6 +11576,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
1154811576
/* Subquery RTE */
1154911577
appendStringInfoChar(buf, '(');
1155011578
get_query_def(rte->subquery, buf, context->namespaces, NULL,
11579+
true,
1155111580
context->prettyFlags, context->wrapColumn,
1155211581
context->indentLevel);
1155311582
appendStringInfoChar(buf, ')');

src/test/regress/expected/matview.out

+2-2
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)