Fix deparsing of ON CONFLICT arbiter WHERE clauses.
authorTom Lane <[email protected]>
Sun, 7 Feb 2016 19:57:24 +0000 (14:57 -0500)
committerTom Lane <[email protected]>
Sun, 7 Feb 2016 19:57:24 +0000 (14:57 -0500)
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
src/test/regress/expected/rules.out

index 4efd2988e793e797bdc759d2305b1c62589bfa64..490a0906e8ed50b488fcbaaaab9aedb262a3937c 100644 (file)
@@ -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",
index 28b061f9d55359352a3a4796a6d166c0d3ea6bb6..2bdba2d1a18d3236ec3d756fa2049b8326a8c034 100644 (file)
@@ -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)