From cc2ca9319a5dbe89ea47d87944650e65e3bb4ce8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 7 Feb 2016 14:57:24 -0500 Subject: [PATCH] Fix deparsing of ON CONFLICT arbiter WHERE clauses. The parser doesn't allow qualification of column names appearing in these clauses, but ruleutils.c would sometimes qualify them, leading to dump/reload failures. Per bug #13891 from Onder Kalaci. (In passing, make stanzas in ruleutils.c that save/restore varprefix more consistent.) Peter Geoghegan --- src/backend/utils/adt/ruleutils.c | 19 ++++++++++++++++--- src/test/regress/expected/rules.out | 4 ++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 4efd2988e7..490a0906e8 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -5532,9 +5532,21 @@ get_insert_query_def(Query *query, deparse_context *context) /* Add a WHERE clause (for partial indexes) if given */ if (confl->arbiterWhere != NULL) { + bool save_varprefix; + + /* + * Force non-prefixing of Vars, since parser assumes that they + * belong to target relation. WHERE clause does not use + * InferenceElem, so this is separately required. + */ + save_varprefix = context->varprefix; + context->varprefix = false; + appendContextKeyword(context, " WHERE ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); get_rule_expr(confl->arbiterWhere, context, false); + + context->varprefix = save_varprefix; } } else if (confl->constraint != InvalidOid) @@ -7956,13 +7968,14 @@ get_rule_expr(Node *node, deparse_context *context, case T_InferenceElem: { InferenceElem *iexpr = (InferenceElem *) node; - bool varprefix = context->varprefix; + bool save_varprefix; bool need_parens; /* * InferenceElem can only refer to target relation, so a - * prefix is never useful. + * prefix is not useful, and indeed would cause parse errors. */ + save_varprefix = context->varprefix; context->varprefix = false; /* @@ -7982,7 +7995,7 @@ get_rule_expr(Node *node, deparse_context *context, if (need_parens) appendStringInfoChar(buf, ')'); - context->varprefix = varprefix; + context->varprefix = save_varprefix; if (iexpr->infercollid) appendStringInfo(buf, " COLLATE %s", diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 28b061f9d5..2bdba2d1a1 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2846,7 +2846,7 @@ SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename; CREATE RULE hat_nosert AS + ON INSERT TO hats DO INSTEAD INSERT INTO hat_data (hat_name, hat_color) + VALUES (new.hat_name, new.hat_color) ON CONFLICT(hat_name COLLATE "C" bpchar_pattern_ops)+ - WHERE (hat_data.hat_color = 'green'::bpchar) DO NOTHING + + WHERE (hat_color = 'green'::bpchar) DO NOTHING + RETURNING hat_data.hat_name, + hat_data.hat_color; (1 row) @@ -2871,7 +2871,7 @@ SELECT tablename, rulename, definition FROM pg_rules hats | hat_nosert | CREATE RULE hat_nosert AS + | | ON INSERT TO hats DO INSTEAD INSERT INTO hat_data (hat_name, hat_color) + | | VALUES (new.hat_name, new.hat_color) ON CONFLICT(hat_name COLLATE "C" bpchar_pattern_ops)+ - | | WHERE (hat_data.hat_color = 'green'::bpchar) DO NOTHING + + | | WHERE (hat_color = 'green'::bpchar) DO NOTHING + | | RETURNING hat_data.hat_name, + | | hat_data.hat_color; (1 row)