Thread: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
onderkalaci@gmail.com
Date:
The following bug has been logged on the website: Bug reference: 13891 Logged by: Onder Kalaci Email address: onderkalaci@gmail.com PostgreSQL version: 9.5.0 Operating system: MacOs Description: Deparsed arbiter WHERE clauses cannot be parsed by Postgres. Please follow the steps below: I create two tables: CREATE TABLE test_1 (a int, b int); CREATE TABLE test_2 (a int UNIQUE, b int); Create a rule: CREATE RULE r3 AS ON INSERT TO test_1 DO INSTEAD INSERT INTO test_2 VALUES (1,1) ON CONFLICT(a) WHERE a > 100 DO UPDATE set b = test_2.b+1; Then, SELECT * FROM pg_rules; I get the following: CREATE RULE r3 AS ON INSERT TO test_1 DO INSTEAD INSERT INTO test_2 (a, b) VALUES (1, 1) ON CONFLICT(a) WHERE (test_2.a > 100) DO UPDATE SET b = (test_2.b + 1); Cutting the query part alone: INSERT INTO test_2 (a, b) VALUES (1, 1) ON CONFLICT(a) WHERE (test_2.a > 100) DO UPDATE SET b = (test_2.b + 1); This query errors out saying: ERROR: invalid reference to FROM-clause entry for table "test_2" LINE 1: ...test_2 (a, b) VALUES (1, 1) ON CONFLICT(a) WHERE (test_2.a >... ^ HINT: There is an entry for table "test_2", but it cannot be referenced from this part of the query. I guess the problem is on this line (ruletils@5533 on Postgresql 9.5.0 source) https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/ruleutils.c#L5533 I think, postgres should set varprefix to false before calling get_rule_expr(). Thanks, Onder
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Peter Geoghegan
Date:
On Tue, Jan 26, 2016 at 4:34 AM, <onderkalaci@gmail.com> wrote: > > I guess the problem is on this line (ruletils@5533 on Postgresql 9.5.0 > source) > https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/ruleutils.c#L5533 > > I think, postgres should set varprefix to false before calling > get_rule_expr(). I believe that your analysis is correct. I'll need to look into it in more detail, but I'm about to get on a transatlantic flight. I'm curious: How did you find this bug? Did you just stumble upon it? I think that the deeper problem here may be that parse analysis of the inference WHERE clause works by reusing infrastructure from CREATE INDEX. We should consider that there may be further consequences to that (although there may well not be). Does the rewritten query actually error? In other words, is your complaint strictly that deparsing is broken? -- Peter Geoghegan
Hi Peter,
Thanks for the quick response.
I'm curious: How did you find this bug? Did you just stumble upon it?
We use postgres' ruleutils.c to build SQL strings. I realized this while I was playing with UPSERTs on 9.5.
Does the rewritten query actually error? In other words, is your
complaint strictly that deparsing is broken?
Yes, the rewritten query actually errors and our complaint is that a deparsed query cannot be parsed by postgres again.
Thanks
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Peter Geoghegan
Date:
On Wed, Jan 27, 2016 at 5:42 AM, Önder Kalacı <onderkalaci@gmail.com> wrote: > We use postgres' ruleutils.c to build SQL strings. I realized this while I > was playing with UPSERTs on 9.5. Here is a bug fix patch. InferenceElem already had appropriate handling for this case. Unfortunately, that did no help with the arbiter WHERE clause, since it does not use InferenceElem. I haven't moved the existing handling; I feel it makes sense to do this separately for each case. Thanks for the report! -- Peter Geoghegan
Attachment
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Andres Freund
Date:
On 2016-02-04 04:02:04 -0800, Peter Geoghegan wrote: > --- 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) Can you add code to execute the resulting statements? Because obviously just seeing the output ain't enough. Seems like an easily repeatable error, and the regression test scase ought to be pretty easy with a DO and a loop. Andres
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Peter Geoghegan
Date:
On Thu, Feb 4, 2016 at 4:11 AM, Andres Freund <andres@anarazel.de> wrote: > Can you add code to execute the resulting statements? Because obviously > just seeing the output ain't enough. Seems like an easily repeatable > error, and the regression test scase ought to be pretty easy with a DO > and a loop. What do you mean? The stored rules whose output was modified as part of the fix are actually executed already -- no change there. =C3=96nder's complaint was that deparsing doesn't work. It was not that stored rules were ever independently broken. --=20 Peter Geoghegan
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Peter Geoghegan
Date:
On Thu, Feb 4, 2016 at 6:16 AM, Peter Geoghegan <pg@heroku.com> wrote: > The stored rules whose output was modified as part of the fix are > actually executed already -- no change there. By which I mean: Real INSERT statements are rewritten and executed, with no obvious trouble. -- Peter Geoghegan
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Andres Freund
Date:
On February 4, 2016 5:16:16 PM GMT+03:00, Peter Geoghegan <pg@heroku.com> wrote: >On Thu, Feb 4, 2016 at 4:11 AM, Andres Freund <andres@anarazel.de> >wrote: >> Can you add code to execute the resulting statements? Because >obviously >> just seeing the output ain't enough. Seems like an easily repeatable >> error, and the regression test scase ought to be pretty easy with a >DO >> and a loop. > >What do you mean? > >The stored rules whose output was modified as part of the fix are >actually executed already -- no change there. Ãnder's complaint was >that deparsing doesn't work. It was not that stored rules were ever >independently broken. I want the deparse output to be executed. Andres --- Please excuse brevity and formatting - I am writing this on my mobile phone.
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Peter Geoghegan
Date:
On Thu, Feb 4, 2016 at 7:15 AM, Andres Freund <andres@anarazel.de> wrote: >>The stored rules whose output was modified as part of the fix are >>actually executed already -- no change there. =C3=96nder's complaint was >>that deparsing doesn't work. It was not that stored rules were ever >>independently broken. > > I want the deparse output to be executed. That seems like something requiring an additional infrastructure. It would be somewhat useful to smoke test lots of things like this. What exactly do you have in mind? --=20 Peter Geoghegan
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Andres Freund
Date:
On 2016-02-04 12:43:15 -0800, Peter Geoghegan wrote: > On Thu, Feb 4, 2016 at 7:15 AM, Andres Freund <andres@anarazel.de> wrote: > >>The stored rules whose output was modified as part of the fix are > >>actually executed already -- no change there. Önder's complaint was > >>that deparsing doesn't work. It was not that stored rules were ever > >>independently broken. > > > > I want the deparse output to be executed. > > That seems like something requiring an additional infrastructure. It > would be somewhat useful to smoke test lots of things like this. What > exactly do you have in mind? Seems fairly simple to write a DO statement that does something like v_sql = pg_get_viewdef(viewname); EXECUTE 'DROP VIEW '||viewname::regclass; EXECUTE v_sql; in a query over pg_views.
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Peter Geoghegan
Date:
On Thu, Feb 4, 2016 at 12:49 PM, Andres Freund <andres@anarazel.de> wrote: > Seems fairly simple to write a DO statement that does something like > v_sql = pg_get_viewdef(viewname); > EXECUTE 'DROP VIEW '||viewname::regclass; > EXECUTE v_sql; > in a query over pg_views. Sorry, I still don't get it. How does that help with ON CONFLICT arbiter WHERE clause deparsing? -- Peter Geoghegan
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Andres Freund
Date:
On 2016-02-04 13:09:43 -0800, Peter Geoghegan wrote: > On Thu, Feb 4, 2016 at 12:49 PM, Andres Freund <andres@anarazel.de> wrote: > > Seems fairly simple to write a DO statement that does something like > > v_sql = pg_get_viewdef(viewname); > > EXECUTE 'DROP VIEW '||viewname::regclass; > > EXECUTE v_sql; > > in a query over pg_views. > > Sorry, I still don't get it. How does that help with ON CONFLICT > arbiter WHERE clause deparsing? The bug this thread is about was actually visible in regression test output, as the wrong output of pg_rules output. As were a number of previous bugs. So it seems time to actually make sure that the output of the rules we generate to test deparsing actually do something remotely sane, by executing the deparsed sql. Obviously human inspection is not sufficient. You can do so by executing deparsed output of a rule or a view (both should be doable afacis).
Andres Freund <andres@anarazel.de> writes: > On 2016-02-04 13:09:43 -0800, Peter Geoghegan wrote: >> Sorry, I still don't get it. How does that help with ON CONFLICT >> arbiter WHERE clause deparsing? > The bug this thread is about was actually visible in regression test > output, as the wrong output of pg_rules output. As were a number of > previous bugs. So it seems time to actually make sure that the output of > the rules we generate to test deparsing actually do something remotely > sane, by executing the deparsed sql. Obviously human inspection is not > sufficient. You can do so by executing deparsed output of a rule or a > view (both should be doable afacis). That's all very well, but we have a release to get out tomorrow, so I went ahead and pushed Peter's patch (with some cosmetic fiddling). I think actually Andres' proposal wouldn't be all that helpful, because it would only detect deparse problems for constructs that happen to appear in views/rules that exist at the instant the test runs. What I'd be inclined to think about is something comparable to the COPY_PARSE_PLAN_TREES #define, that is an option to make postgres.c pass every non-utility statement through deparse and reparse and then compare the resulting parse trees. It'd be a bit slow but it would cover every type of syntax exercised anywhere in the regression tests. regards, tom lane
Re: BUG #13891: Deparsed arbiter WHERE clauses cannot be parsed by Postgres
From
Andres Freund
Date:
On February 7, 2016 9:02:11 PM GMT+01:00, Tom Lane <tgl@sss.pgh.pa.us> wrote: >Andres Freund <andres@anarazel.de> writes: >I think actually Andres' proposal wouldn't be all that helpful, because >it would only detect deparse problems for constructs that happen to >appear in views/rules that exist at the instant the test runs. That's be fine for this purpose. This specific line had two hard to spot roots already... --- Please excuse brevity and formatting - I am writing this on my mobile phone.