Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-24 Thread Stephen Frost
Peter,

* Peter Geoghegan (p...@heroku.com) wrote:
 I came up with something that is along the lines of what we discussed.
 I'll wait for you to push Dean's code, and rebase on top of that
 before submitting what I came up with. Maybe this can be rolled into
 my next revision if I work through Andres' most recent feedback
 without much delay.

This is done (finally!).  Please take a look and let me know if you have
any questions or concerns.  Happy to chat again also, of course.

Thanks!

Stephen


signature.asc
Description: Digital signature


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-24 Thread Peter Geoghegan
On Fri, Apr 24, 2015 at 5:50 PM, Stephen Frost sfr...@snowman.net wrote:
 * Peter Geoghegan (p...@heroku.com) wrote:
 I came up with something that is along the lines of what we discussed.
 I'll wait for you to push Dean's code, and rebase on top of that
 before submitting what I came up with. Maybe this can be rolled into
 my next revision if I work through Andres' most recent feedback
 without much delay.

 This is done (finally!).  Please take a look and let me know if you have
 any questions or concerns.  Happy to chat again also, of course.

Great, thanks.

I didn't actually wait for you (as earlier indicated) before posting
the new approach to RLS in V3.4. However, I have some decent tests for
the new behaviors (I did test-driven development), so I think that
when I rebase on top of the new RLS stuff tomorrow, I'll find that it
won't be too difficult.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-24 Thread Stephen Frost
* Peter Geoghegan (p...@heroku.com) wrote:
 On Fri, Apr 24, 2015 at 5:50 PM, Stephen Frost sfr...@snowman.net wrote:
  * Peter Geoghegan (p...@heroku.com) wrote:
  I came up with something that is along the lines of what we discussed.
  I'll wait for you to push Dean's code, and rebase on top of that
  before submitting what I came up with. Maybe this can be rolled into
  my next revision if I work through Andres' most recent feedback
  without much delay.
 
  This is done (finally!).  Please take a look and let me know if you have
  any questions or concerns.  Happy to chat again also, of course.
 
 Great, thanks.
 
 I didn't actually wait for you (as earlier indicated) before posting
 the new approach to RLS in V3.4. However, I have some decent tests for
 the new behaviors (I did test-driven development), so I think that
 when I rebase on top of the new RLS stuff tomorrow, I'll find that it
 won't be too difficult.

Fantastic, glad to hear it!

Thanks!

Stephen


signature.asc
Description: Digital signature


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-24 Thread Peter Geoghegan
On Thu, Apr 23, 2015 at 6:07 PM, Peter Geoghegan p...@heroku.com wrote:
 Curious about what you think about my proposal to go back to putting
 the inference specification WHERE clause within the parenthesis, since
 this solves several problems, including clarifying to users that the
 predicate is part of the inference clause.

I've *provisionally* pushed code that goes back to the old way,
Andres: 
https://github.com/petergeoghegan/postgres/commit/2a5d80b27d2c5832ad26dde4651c64dd2004f401

Perhaps this is the least worst way, after all.
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-24 Thread Heikki Linnakangas

On 04/24/2015 02:52 AM, Peter Geoghegan wrote:

I found a bug that seems to be down to commit
e3144183562d08e347f832f0b29daefe8bac617b on Github:


commit e3144183562d08e347f832f0b29daefe8bac617b
Author: Heikki Linnakangas heikki.linnakan...@iki.fi
Date:   Thu Apr 23 18:38:11 2015 +0300

 Minor cleanup of check_exclusion_or_unique_constraint.

 To improve readability.



At least, that's what a git bisect session showed.


Ok, I see now that I totally screwed up the conditions on waitMode in 
that commit. I just pushed a fix to your github repository.


- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-24 Thread Peter Geoghegan
On Fri, Apr 24, 2015 at 12:31 AM, Heikki Linnakangas hlinn...@iki.fi wrote:
 Ok, I see now that I totally screwed up the conditions on waitMode in that
 commit. I just pushed a fix to your github repository.

I can confirm that the commit you just pushed prevents the
implementation from attempting to lock an invisible tuple, where
previously it would reliably fall given the same testcase.

Thanks
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Geoff Winkless
On 23 April 2015 at 14:50, Andres Freund and...@anarazel.de wrote:

  ​Maybe I'm misreading it, but isn't index_predicate meant to be inside
 the
  brackets?
 
 
 http://postgres-benchmarks.s3-website-us-east-1.amazonaws.com/on-conflict-docs/sql-insert.html

 That has changed since.


​Oh, helpful. :)​

​I'll shut up. I have a feeling that my objection is really with the very
idea of unreserved keywords and I have a feeling that there will be rather
more people shouting me down if I go off on that particular rant; meanwhile
it's 20 years since I used yacc in earnest and it's too hazy to be able to
argue about what it is or isn't capable of.

When I set out I was really only hoping to express a preference as a user;
on balance I would really rather not have DO IGNORE, if it were possible to
avoid, because it's really ugly, but DO UPDATE/DO NOTHING I could just
about cope with (and means you don't need to add IGNORE as a keyword,
win!), although it still mildly pains me that there's an additional
unnecessary word.

But I certainly don't object enough to hold up you guys doing the actual
work for my benefit (among others, obviously!).

G


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On 2015-04-23 15:52:40 +0100, Geoff Winkless wrote:
 When I set out I was really only hoping to express a preference as a user;
 on balance I would really rather not have DO IGNORE, if it were possible to
 avoid, because it's really ugly, but DO UPDATE/DO NOTHING I could just
 about cope with (and means you don't need to add IGNORE as a keyword,
 win!), although it still mildly pains me that there's an additional
 unnecessary word.

Yea, DO NOTHING is a good alternative. And I do like we're adding one
keyword less (which is also good for the parser's
size/performance).

DO {UPDATE ... | NOTHING | LOCK} doesn't sound too bad to me (yes, LOCK
doesn't exist yet, except by writing UPDATE .. WHERE false ;)).

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Bruce Momjian
On Thu, Apr 23, 2015 at 05:02:19PM +0200, Andres Freund wrote:
 On 2015-04-23 15:52:40 +0100, Geoff Winkless wrote:
  When I set out I was really only hoping to express a preference as a user;
  on balance I would really rather not have DO IGNORE, if it were possible to
  avoid, because it's really ugly, but DO UPDATE/DO NOTHING I could just
  about cope with (and means you don't need to add IGNORE as a keyword,
  win!), although it still mildly pains me that there's an additional
  unnecessary word.
 
 Yea, DO NOTHING is a good alternative. And I do like we're adding one
 keyword less (which is also good for the parser's
 size/performance).

No question that DO IGNORE sounds awkward.  DO NOTHING also matches
CREATE RULE --- another plus.

-- 
  Bruce Momjian  br...@momjian.ushttp://momjian.us
  EnterpriseDB http://enterprisedb.com

  + Everyone has their own god. +


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Heikki Linnakangas

On 04/23/2015 10:53 PM, Andres Freund wrote:

On 2015-04-23 12:45:59 -0700, Peter Geoghegan wrote:

On Thu, Apr 23, 2015 at 12:55 AM, Andres Freund and...@anarazel.de wrote:

I think you misread my statement: I'm saying we don't need the new
argument anymore, even if we still do the super-deletion in
heap_delete(). Now that the speculative insertion will not be visible
(as in seen on a tuple they could delete) to other backends we can just
do the super deletion if we see that the tuple is a promise one.


I disagree. I think it's appropriate that the one and only super
heap_delete() caller make a point of indicating that that's what it's
doing. The cost is only that the two other such callers must say that
they're not doing it. Super deletion is a special thing, that logical
decoding knows all about for example, and I think it's appropriate
that callers ask explicitly.


Unconvinced. Not breaking an API has its worth.


The heapam API is not that stable, we've added arguments to those 
functions every once in a while, and I don't recall any complaints. So 
I'm with Peter that super-deletion should be requested explicitly by the 
caller.


That said, I'd actually like to see a separate heap_super_delete() 
function for that, rather than piggybacking on heap_delete(). It's a 
quite different operation. There'll be some duplication, but seems 
better than a maze of if-else's in heap_delete.


- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On 2015-04-23 12:45:59 -0700, Peter Geoghegan wrote:
 On Thu, Apr 23, 2015 at 12:55 AM, Andres Freund and...@anarazel.de wrote:
  I think you misread my statement: I'm saying we don't need the new
  argument anymore, even if we still do the super-deletion in
  heap_delete(). Now that the speculative insertion will not be visible
  (as in seen on a tuple they could delete) to other backends we can just
  do the super deletion if we see that the tuple is a promise one.
 
 I disagree. I think it's appropriate that the one and only super
 heap_delete() caller make a point of indicating that that's what it's
 doing. The cost is only that the two other such callers must say that
 they're not doing it. Super deletion is a special thing, that logical
 decoding knows all about for example, and I think it's appropriate
 that callers ask explicitly.

Unconvinced. Not breaking an API has its worth.

 The second most significant open item is rebasing on top of the recent
 RLS changes, IMV.

Not sure I agree. That part seems pretty mechanical to me.

* The docs aren't suitable for endusers. I think this will take a fair
  amount of work.

* We're not yet sure about the syntax yet. In addition to the keyword
  issue I'm unconvinced about having two WHERE clauses in the same
  statement. I think that'll end up confusing users a fair bit. Might
  still be the best way forward.
* The executor integration still isn't pretty, although Heikki is making
  strides there
* I don't think anybody seriously has looked at the planner side yet.

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Peter Geoghegan
On Thu, Apr 23, 2015 at 12:55 AM, Andres Freund and...@anarazel.de wrote:
 I think you misread my statement: I'm saying we don't need the new
 argument anymore, even if we still do the super-deletion in
 heap_delete(). Now that the speculative insertion will not be visible
 (as in seen on a tuple they could delete) to other backends we can just
 do the super deletion if we see that the tuple is a promise one.

I disagree. I think it's appropriate that the one and only super
heap_delete() caller make a point of indicating that that's what it's
doing. The cost is only that the two other such callers must say that
they're not doing it. Super deletion is a special thing, that logical
decoding knows all about for example, and I think it's appropriate
that callers ask explicitly.

  * breinbaas on IRC just mentioned that it'd be nice to have upsert as a
link in the insert. Given that that's the pervasive term that doesn't
seem absurd.

 Not sure what you mean. Where would the link appear?

 The index, i.e. it'd just be another indexterm. It seems good to give
 people a link.

Oh, okay. Sure. Done on Github.

 * We need to figure out the tuple lock strength details. I think this
 is doable, but it is the greatest challenge to committing ON CONFLICT
 UPDATE at this point. Andres feels that we should require no greater
 lock strength than an equivalent UPDATE. I suggest we get to this
 after committing the IGNORE variant. We probably need to discuss this
 some more.

 I want to see a clear way forward before we commit parts. It doesn't
 have to be completely iron-clad, but the way forward should be pretty
 clear. What's the problem you're seeing right now making this work? A
 couple days on jabber you seemed to see a way doing this?

I was really just identifying it as the biggest problem the patch now
faces, and I want to face those issues down ASAP. Of course, that's
good, because as you say it is a small problem in an absolute sense.
The second most significant open item is rebasing on top of the recent
RLS changes, IMV.

I can see yourself and Heikki continuing to change small stylistic
things, which I expect to continue for a little while. That's fine,
but naturally I want to be aggressive about closing off these open
issues that are not just general clean-up, but have some small level
of risk of becoming more significant blockers.

 The reason I think this has to use the appropriate lock level is that
 it'll otherwise re-introduce the deadlocks that fk locks resolved. Given
 how much pain we endured to get fk locks, that seems like a bad deal.

Right.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Peter Geoghegan
On Thu, Apr 23, 2015 at 12:53 PM, Andres Freund and...@anarazel.de wrote:
 Unconvinced. Not breaking an API has its worth.

Yeah, and I acknowledge that - but it's not something that it's
appropriate to encapsulate IMV.

Let's just leave it to Heikki...I'd say he has the deciding vote,
especially as the reviewer that is more in charge of the executor
stuff than anything else.

 The second most significant open item is rebasing on top of the recent
 RLS changes, IMV.

 Not sure I agree. That part seems pretty mechanical to me.

Hopefully so.

 * The docs aren't suitable for endusers. I think this will take a fair
   amount of work.

It's hard to explain why something like the collation field in the
inference specification matters to users...because it's only supported
at all due to forwards compatibility concerns. It's hard to document
certain things like that in an accessible way. In general, much of the
effort of the last year was making the feature play nice, and
considering a bunch of usability edge cases that are unlikely to come
up, but still must be documented.

 * We're not yet sure about the syntax yet. In addition to the keyword
   issue I'm unconvinced about having two WHERE clauses in the same
   statement. I think that'll end up confusing users a fair bit. Might
   still be the best way forward.

My previous approach to allowing an index predicate did at least
clearly show that the predicate belonged to the inference
specification, since it appeared between parenthesis. Maybe we should
do that after all? I don't think it much matters if the inference
specification is not identical to CREATE INDEX. I don't want to give
up inference of partial indexes, and I don't want to give up allowing
the UPDATE to have a limited WHERE clause, and we can't just spell
those differently here. So what alternative does that leave?

Anyone else have an opinion?

 * The executor integration still isn't pretty, although Heikki is making
   strides there

That's just clean-up, though. I'm not worried about the risk of Heikki
not succeeding at that.

 * I don't think anybody seriously has looked at the planner side yet.

Good point. That certainly needs to be looked at (and I include the
rewriter parts in that). It's really not that much code, but (ideally)
a subject matter expert should look into the whole ExcludedExpr dance
in particular.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On 2015-04-23 23:08:34 +0300, Heikki Linnakangas wrote:
 The heapam API is not that stable, we've added arguments to those functions
 every once in a while, and I don't recall any complaints.

I heard some, but not too many, that's true. I know that I've written
code that'd be broken/needed even more ifdefs ;)

 That said, I'd actually like to see a separate heap_super_delete() function
 for that, rather than piggybacking on heap_delete(). It's a quite different
 operation. There'll be some duplication, but seems better than a maze of
 if-else's in heap_delete.

+many. I've requested that changes a couple times now.

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Peter Geoghegan
On Thu, Apr 23, 2015 at 12:45 PM, Peter Geoghegan p...@heroku.com wrote:
 * We need to figure out the tuple lock strength details. I think this
 is doable, but it is the greatest challenge to committing ON CONFLICT
 UPDATE at this point. Andres feels that we should require no greater
 lock strength than an equivalent UPDATE. I suggest we get to this
 after committing the IGNORE variant. We probably need to discuss this
 some more.

 I want to see a clear way forward before we commit parts. It doesn't
 have to be completely iron-clad, but the way forward should be pretty
 clear. What's the problem you're seeing right now making this work? A
 couple days on jabber you seemed to see a way doing this?

 I was really just identifying it as the biggest problem the patch now
 faces, and I want to face those issues down ASAP. Of course, that's
 good, because as you say it is a small problem in an absolute sense.
 The second most significant open item is rebasing on top of the recent
 RLS changes, IMV.


OK, I pushed out code to do this a while ago. I must admit that I
probably significantly over-estimated the difficulty of doing this.

With Heikki's problematic commit reverted this works fine  (I have not
actually reverted it myself...I'll leave it to Heikki to clean that up
when he gets around to it). The usually jjanes_upsert stress tests
show up no problems.

Curious about what you think about my proposal to go back to putting
the inference specification WHERE clause within the parenthesis, since
this solves several problems, including clarifying to users that the
predicate is part of the inference clause.
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On 2015-04-23 14:34:02 +0100, Geoff Winkless wrote:
  A syntax error. DO is a reserved keyword. Update is just unreserved (and
  thus can be used as a column label). Ignore is unreserved with the patch
  and was unreserved before.  We obviously can make both reserved, but of so
  we have to do it for real, not by hiding the conflicts
 
 
 Sorry, I misunderstood: so it's not the fact that it can't be used as a
 column label (because it can) but the fact that it can't then be referenced
 within a WHERE clause without quoting

Meh. You can use any keyword in quotes - because then they're not
keywords anymore.


 INSERT INTO mytable (somevalue) VALUES (999) ON CONFLICT ('myindex') WHERE
 update UPDATE update=1
 
 but I would have to do
 
 INSERT INTO mytable (somevalue) VALUES (999) ON CONFLICT ('myindex') WHERE
 do UPDATE do=1

Yes.

 ​Maybe I'm misreading it, but isn't index_predicate meant to be inside the
 brackets?
 
 http://postgres-benchmarks.s3-website-us-east-1.amazonaws.com/on-conflict-docs/sql-insert.html

That has changed since. And for good reason: It's pretty to have the
WHERE clause inside the brackets when that's not the case for CREATE
INDEX. But more importantly with multiple columns for stuff like ON
CONFLICT (a, b WHERE foo) it's unclear where the WHERE is actually
attached to. We have that problem with aggregates and it repeatedly
caused confusion.

 ​As I said, it's my personal belief that anyone using keywords (of any
 kind) unquoted deserves what they get, but I see your point.​

Given that IGNORE isn't even a keyword right now (9.5 master) that
policy isn't particularly meaningful anyway.

 I think I object to the fact that you're talking about adding extra
 syntactic sugar to work around a parser-implementation problem, not an
 actual syntax problem (since UPDATE SET is unambiguous, isn't it?).

I fail to see the point of such an objection. We have an LALR parser
(generated by bison). That implies a certain expressiveness. You're
suggesting that we change to a different kind of parser?

I don't think it's necessarily unambiguous. I'm not particularly
motivated to prove it though - the point is that we rely on bison to
prevent ambiguities. That only works if we're listening. And not if
we're silencing warnings about ambiguities over the whole grammar.

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On 2015-04-22 15:23:16 -0700, Peter Geoghegan wrote:
 On Tue, Apr 21, 2015 at 7:57 AM, Andres Freund and...@anarazel.de wrote:
  * Iff we're going to have the XLOG_HEAP_AFFIRM record, I'd rather have
that guide the logical decoding code. Seems slightly cleaner.
 
 I thought that you didn't think that would always work out? That in
 some possible scenario it could break?

I don't think there's a real problem. You obviously have to do it right
(i.e. only abort insertion if there's a insert/update/delete or commit).

Speaking of commits: Without having rechecked: I think you're missing
cleanup of th pending insertion on commit.

  * Gram.y needs a bit more discussion:
* Can anybody see a problem with changing the precedence of DISTINCT 
  ON to nonassoc? Right now I don't see a problem given both are
  reserved keywords already.
 
 Why did you push code that solved this in a roundabout way, but
 without actually reverting my original nonassoc changes (which would
 now not result in shift/reduce conflicts?).

I pushed the changes to a separate repo so you could polish them ;)

 What should we do about that?

I'm prety sure we should not do the %nonassoc stuff.

 I don't like that you seem to have regressed
 diagnostic output [1].

Meh^5. This is the same type of errors we get in literally hundreds of
other syntax errors. And in contrast to the old error it'll actually
have a correct error possition.

 Surely it's simpler to use the nonassoc approach?

I think it's much harder to forsee all consequences of that.

  * SPEC_IGNORE,  /* INSERT of ON CONFLICT IGNORE */ looks like
a wrongly copied comment.
 
 Not sure what you mean here. Please clarify.

I'm not sure either ;)

  * I wonder if we now couldn't avoid changing heap_delete's API - we can
always super delete if we find a speculative insertion now. It'd be
nice not to break out of core callers if not necessary.
 
 Maybe, but if there is a useful way to break out only a small subset
 of heap_delete(), I'm not seeing it.

I think you misread my statement: I'm saying we don't need the new
argument anymore, even if we still do the super-deletion in
heap_delete(). Now that the speculative insertion will not be visible
(as in seen on a tuple they could delete) to other backends we can just
do the super deletion if we see that the tuple is a promise one.

  * breinbaas on IRC just mentioned that it'd be nice to have upsert as a
link in the insert. Given that that's the pervasive term that doesn't
seem absurd.
 
 Not sure what you mean. Where would the link appear?

The index, i.e. it'd just be another indexterm. It seems good to give
people a link.

 * We need to figure out the tuple lock strength details. I think this
 is doable, but it is the greatest challenge to committing ON CONFLICT
 UPDATE at this point. Andres feels that we should require no greater
 lock strength than an equivalent UPDATE. I suggest we get to this
 after committing the IGNORE variant. We probably need to discuss this
 some more.

I want to see a clear way forward before we commit parts. It doesn't
have to be completely iron-clad, but the way forward should be pretty
clear. What's the problem you're seeing right now making this work? A
couple days on jabber you seemed to see a way doing this?

The reason I think this has to use the appropriate lock level is that
it'll otherwise re-introduce the deadlocks that fk locks resolved. Given
how much pain we endured to get fk locks, that seems like a bad deal.

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On 2015-04-22 16:40:07 -0700, Peter Geoghegan wrote:
 On Wed, Apr 22, 2015 at 3:23 PM, Peter Geoghegan p...@heroku.com wrote:
  * We need to sort out those issues with the grammar, since that only
  really applies to the inference specification. Maybe the WHERE clause
  that the inference specification accepts can be broken out. No ON
  CONFLICT UPDATE specific issues left there, AFAICT though.

 I pushed some code that deals with the predicate being within parenthesis:

 https://github.com/petergeoghegan/postgres/commit/358854645279523310f998dfc9cb3fe3e165ce1e

And the way you've used nonassoc here doesn't look correct. You're
hiding legitimate ambiguities in the grammar. UPDATE is a unreserved
keyword, so for

... ON CONFLICT '(' index_params ')' where_clause OnConflictUpdateStmt

it won't be able to discern whether an UPDATE in the WHERE clause is
part of the where_clause or OnConflictUpdate.

This is legal:
SELECT * FROM (SELECT true as update) f WHERE update;
i.e. 'update' can be the last part of a WHERE clause.

Essentially what you're trying to do with the nonassic is hiding that
UPDATE and IGNORE need to be reserved keywords with the syntax you're
proposing. We can either make them reserved or change the syntax.

One way to avoid making them reserved keywords - which would be somewhat
painful - is to add a 'DO' before the IGNORE/UPDATE. I.e. something like

  ON CONFLICT opt_conflict_expr DO OnConflictUpdateStmt
| ON CONFLICT opt_conflict_expr DO IGNORE

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Geoff Winkless
Apologies for butting in but can I (as a user) express a preference as a
user against DO?

Firstly, it looks horrible. And what's to stop me having SELECT true AS
do in the where clause (as per your UPDATE objection)?

Shouldn't UPDATE be a reserved keyword anyway? AIUI ANSI suggests so.

http://developer.mimer.se/validator/sql-reserved-words.tml

I had always assumed it was; anyone who produced a query for me that
contained update in an unusual context would get slapped heavily.

Geoff

On 23 April 2015 at 11:54, Andres Freund and...@anarazel.de wrote:

 On 2015-04-22 16:40:07 -0700, Peter Geoghegan wrote:
  On Wed, Apr 22, 2015 at 3:23 PM, Peter Geoghegan p...@heroku.com wrote:
   * We need to sort out those issues with the grammar, since that only
   really applies to the inference specification. Maybe the WHERE clause
   that the inference specification accepts can be broken out. No ON
   CONFLICT UPDATE specific issues left there, AFAICT though.
 
  I pushed some code that deals with the predicate being within
 parenthesis:
 
 
 https://github.com/petergeoghegan/postgres/commit/358854645279523310f998dfc9cb3fe3e165ce1e

 And the way you've used nonassoc here doesn't look correct. You're
 hiding legitimate ambiguities in the grammar. UPDATE is a unreserved
 keyword, so for

 ... ON CONFLICT '(' index_params ')' where_clause OnConflictUpdateStmt

 it won't be able to discern whether an UPDATE in the WHERE clause is
 part of the where_clause or OnConflictUpdate.

 This is legal:
 SELECT * FROM (SELECT true as update) f WHERE update;
 i.e. 'update' can be the last part of a WHERE clause.

 Essentially what you're trying to do with the nonassic is hiding that
 UPDATE and IGNORE need to be reserved keywords with the syntax you're
 proposing. We can either make them reserved or change the syntax.

 One way to avoid making them reserved keywords - which would be somewhat
 painful - is to add a 'DO' before the IGNORE/UPDATE. I.e. something like

   ON CONFLICT opt_conflict_expr DO OnConflictUpdateStmt
 | ON CONFLICT opt_conflict_expr DO IGNORE

 Greetings,

 Andres Freund


 --
 Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
 To make changes to your subscription:
 http://www.postgresql.org/mailpref/pgsql-hackers



Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Petr Jelinek

On 23/04/15 14:34, Geoff Winkless wrote:

Apologies for butting in but can I (as a user) express a preference as a
user against DO?

Firstly, it looks horrible. And what's to stop me having SELECT true AS
do in the where clause (as per your UPDATE objection)?



DO is already reserved keyword. There is also some precedence for this 
in CREATE RULE. But I agree that it's not ideal syntax.



Shouldn't UPDATE be a reserved keyword anyway? AIUI ANSI suggests so.

http://developer.mimer.se/validator/sql-reserved-words.tml

I had always assumed it was; anyone who produced a query for me that
contained update in an unusual context would get slapped heavily.


Postgres currently has UPDATE as unreserved keyword and more importantly 
IGNORE is not keyword at all so making it a new reserved keyword is not 
nice at all.


--
 Petr Jelinek  http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training  Services


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Andres Freund
On April 23, 2015 3:34:07 PM GMT+03:00, Geoff Winkless pgsqlad...@geoff.dj 
wrote:
Apologies for butting in but can I (as a user) express a preference as
a
user against DO?

Sure. If you propose an alternative ;)

Firstly, it looks horrible. And what's to stop me having SELECT true
AS
do in the where clause (as per your UPDATE objection)?

A syntax error. DO is a reserved keyword. Update is just unreserved (and thus 
can be used as a column label). Ignore is unreserved with the patch and was 
unreserved before.  We obviously can make both reserved, but of so we have to 
do it for real, not by hiding the conflicts 

Shouldn't UPDATE be a reserved keyword anyway? AIUI ANSI suggests so.

http://developer.mimer.se/validator/sql-reserved-words.tml

It's not one right now. And ignore isn't a keyword at all atm.

(Please don't top post)

Andres


--- 
Please excuse brevity and formatting - I am writing this on my mobile phone.


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-23 Thread Geoff Winkless
On 23 April 2015 at 13:51, Andres Freund and...@anarazel.de wrote:

 On April 23, 2015 3:34:07 PM GMT+03:00, Geoff Winkless 
 pgsqlad...@geoff.dj wrote:
 ​
 ​​
  And what's to stop me having SELECT true
 ​
 AS

do in the where clause (as per your UPDATE objection)?

 A syntax error. DO is a reserved keyword. Update is just unreserved (and
 thus can be used as a column label). Ignore is unreserved with the patch
 and was unreserved before.  We obviously can make both reserved, but of so
 we have to do it for real, not by hiding the conflicts


Sorry, I misunderstood: so it's not the fact that it can't be used as a
column label (because it can) but the fact that it can't then be referenced
within a WHERE clause without quoting
. Which is in itself utterly horrible, but that's a separate argument and I
can at least now understand your point.​

So I could end up with

INSERT INTO mytable (somevalue) VALUES (999) ON CONFLICT ('myindex') WHERE
update UPDATE update=1

but I would have to do

INSERT INTO mytable (somevalue) VALUES (999) ON CONFLICT ('myindex') WHERE
do UPDATE do=1

?

​
 Apologies for butting in but can I (as a user) express a preference as
 a
 ​
 user against DO?

 Sure. If you propose an alternative ;)


​Maybe I'm misreading it, but isn't index_predicate meant to be inside the
brackets?

http://postgres-benchmarks.s3-website-us-east-1.amazonaws.com/on-conflict-docs/sql-insert.html

certainly states that.

It's not one right now. And ignore isn't a keyword at all atm.


​As I said, it's my personal belief that anyone using keywords (of any
kind) unquoted deserves what they get, but I see your point.​


I think I object to the fact that you're talking about adding extra
syntactic sugar to work around a parser-implementation problem, not an
actual syntax problem (since UPDATE SET is unambiguous, isn't it?).

(Please don't top post)


Mea culpa. I blame google :)​

FWIW DO IGNORE just reads disgustingly. If you do finally go down the DO
route, perhaps DO NOTHING? :)

Geoff


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-22 Thread Peter Geoghegan
On Wed, Apr 22, 2015 at 3:23 PM, Peter Geoghegan p...@heroku.com wrote:
 * We need to sort out those issues with the grammar, since that only
 really applies to the inference specification. Maybe the WHERE clause
 that the inference specification accepts can be broken out. No ON
 CONFLICT UPDATE specific issues left there, AFAICT though.

I pushed some code that deals with the predicate being within parenthesis:

https://github.com/petergeoghegan/postgres/commit/358854645279523310f998dfc9cb3fe3e165ce1e

(it now follows the attributes/expressions indexes, in the style of
CREATE INDEX).

We still need to reconcile these changes to the grammar with your own,
Andres. I'm going to wait to hear back on what you think about that.
Note that this removal:

-%nonassoc DISTINCT
-%nonassoc ON

was incidental to the commit (this is the code you could have removed
when you modified the grammar, adding a new production, but didn't).
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-22 Thread Peter Geoghegan
On Tue, Apr 21, 2015 at 7:57 AM, Andres Freund and...@anarazel.de wrote:
 I'm not 100% sure Heikki and I am on exactly the same page here :P

 I'm looking at git diff $(git merge-base upstream/master HEAD).. where
 HEAD is e1a5822d164db0.

Merged your stuff into my Github branch. Heikki is pushing changes
there directly now.

 * The logical stuff looks much saner.

Cool.

 * Please add tests for the logical decoding stuff. Probably both a plain
   regression and and isolationtester test in
   contrib/test_decoding. Including one that does spooling to disk.

Working on it...hope to push that to Github soon.

 * I don't like REORDER_BUFFER_CHANGE_INTERNAL_INSERT/DELETE as names. Why not
   _SPECINSERT and _SPECDELETE or such?

Changed that on Github.

 * Iff we're going to have the XLOG_HEAP_AFFIRM record, I'd rather have
   that guide the logical decoding code. Seems slightly cleaner.

I thought that you didn't think that would always work out? That in
some possible scenario it could break?

 * Still not a fan of the name 'arbiter' for the OC indexes.

What do you prefer? Seems to describe what we're talking about
reasonably well to me.

 * Gram.y needs a bit more discussion:
   * Can anybody see a problem with changing the precedence of DISTINCT 
 ON to nonassoc? Right now I don't see a problem given both are
 reserved keywords already.

Why did you push code that solved this in a roundabout way, but
without actually reverting my original nonassoc changes (which would
now not result in shift/reduce conflicts?). What should we do about
that? Seems your unsure (otherwise you'd have reverted my thing). I
don't like that you seem to have regressed diagnostic output [1].
Surely it's simpler to use the nonassoc approach? I think this works
by giving the relevant keywords an explicit priority lower than '(',
so that a rule with ON CONFLICT '(' will shift rather than reducing a
conflicting rule (CONFLICT is an unreserved keyword). I wrote the code
so long ago that I can't really remember why I thought it was the
right thing, though.

   * UpdateInsertStmt is a horrible name. OnConflictUpdateStmt maybe?

Done on Github.

   * '(' index_params where_clause ')' is imo rather strange. The where
 clause is inside the parens? That's quite different from the
 original index clause.

I don't know. Maybe I was lazy about fixing shift/reduce conflicts.   :-)

I'll look at this some more.

 * SPEC_IGNORE,  /* INSERT of ON CONFLICT IGNORE */ looks like
   a wrongly copied comment.

Not sure what you mean here. Please clarify.

 * The indentation in RoerderBufferCommit is clearly getting out of hand,
   I've queued up a commit cleaning this up in my repo, feel free to merge.

Done on Github.

 * I don't think we use the term 'ordinary table' in error messages so
   far.

Fixed on Github.

 * I still think it's unacceptable to redefine
   XLOG_HEAP_LAST_MULTI_INSERT as XLOG_HEAP_SPECULATIVE_TUPLE like you
   did. I'll try to find something better.

I did what you suggested in your follow-up e-mail (changes are on Github [2]).

 * I wonder if we now couldn't avoid changing heap_delete's API - we can
   always super delete if we find a speculative insertion now. It'd be
   nice not to break out of core callers if not necessary.

Maybe, but if there is a useful way to break out only a small subset
of heap_delete(), I'm not seeing it. Most of the callers that need a
new NULL argument are heap_insert() callers, actually. There are now 3
heap_delete() callers, up from 2.

 * breinbaas on IRC just mentioned that it'd be nice to have upsert as a
   link in the insert. Given that that's the pervasive term that doesn't
   seem absurd.

Not sure what you mean. Where would the link appear? It is kind of
hard to categorize that text so that we're strictly either talking
about INSERT or UPSERT. Might be possible, though.

 I think this is getting closer to a commit. Let's get this done.

Great!

The blockers to committing the IGNORE patch I see are:

* We need to tweak some of the logical decoding stuff a bit more, I
feel. Firm up on the details of whether we treat a confirmation record
as a logical decoding change that is involved in the new dance during
transaction reassembly.

* We need to sort out those issues with the grammar, since that only
really applies to the inference specification. Maybe the WHERE clause
that the inference specification accepts can be broken out. No ON
CONFLICT UPDATE specific issues left there, AFAICT though.

That really seems totally doable in just a couple of days.

The blockers for committing the ON CONFLICT UPDATE patch are larger, but doable:

* We need to figure out the tuple lock strength details. I think this
is doable, but it is the greatest challenge to committing ON CONFLICT
UPDATE at this point. Andres feels that we should require no greater
lock strength than an equivalent UPDATE. I suggest we get to this
after committing the IGNORE variant. We probably need to discuss this
some 

Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-21 Thread Andres Freund
On 2015-04-19 21:37:51 -0700, Peter Geoghegan wrote:
 Attached patch, V3.4, implements what I believe you and Heikki have in
 mind here.

I'm not 100% sure Heikki and I am on exactly the same page here :P

I'm looking at git diff $(git merge-base upstream/master HEAD).. where
HEAD is e1a5822d164db0.

* The logical stuff looks much saner.

* Please add tests for the logical decoding stuff. Probably both a plain
  regression and and isolationtester test in
  contrib/test_decoding. Including one that does spooling to disk.

* I don't like REORDER_BUFFER_CHANGE_INTERNAL_INSERT/DELETE as names. Why not
  _SPECINSERT and _SPECDELETE or such?

* Iff we're going to have the XLOG_HEAP_AFFIRM record, I'd rather have
  that guide the logical decoding code. Seems slightly cleaner.

* Still not a fan of the name 'arbiter' for the OC indexes.

* Gram.y needs a bit more discussion:
  * Can anybody see a problem with changing the precedence of DISTINCT 
ON to nonassoc? Right now I don't see a problem given both are
reserved keywords already.
The reason the conflict exists AFAICS is because something like
INSERT INTO foo SELECT DISTINCT ON CONFLICT IGNORE;
is allowed by the grammar. The need for the nonassoc could be
avoided by requiring DISTINCT to be followed by a column. We
currently *do* enforce that, just not in the parser (c.f.
transformDistinctClause). That requires one more production in
simple_select, and a nonoptional distinct clause.
I've queued up a commit cleaning this up in my repo, feel free to
merge and polish.
  * UpdateInsertStmt is a horrible name. OnConflictUpdateStmt maybe?
  * '(' index_params where_clause ')' is imo rather strange. The where
clause is inside the parens? That's quite different from the
original index clause.
* SPEC_IGNORE,  /* INSERT of ON CONFLICT IGNORE */ looks like
  a wrongly copied comment.
* The indentation in RoerderBufferCommit is clearly getting out of hand,
  I've queued up a commit cleaning this up in my repo, feel free to merge.
* I don't think we use the term 'ordinary table' in error messages so
  far.
* I still think it's unacceptable to redefine
  XLOG_HEAP_LAST_MULTI_INSERT as XLOG_HEAP_SPECULATIVE_TUPLE like you
  did. I'll try to find something better.
* I wonder if we now couldn't avoid changing heap_delete's API - we can
  always super delete if we find a speculative insertion now. It'd be
  nice not to break out of core callers if not necessary.
* breinbaas on IRC just mentioned that it'd be nice to have upsert as a
  link in the insert. Given that that's the pervasive term that doesn't
  seem absurd.

I think this is getting closer to a commit. Let's get this done.

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-21 Thread Andres Freund
On 2015-04-21 16:57:45 +0200, Andres Freund wrote:
 * I still think it's unacceptable to redefine
   XLOG_HEAP_LAST_MULTI_INSERT as XLOG_HEAP_SPECULATIVE_TUPLE like you
   did. I'll try to find something better.

I think we should just split this into different flag values for
insert/update/delete.

I.e. something like

/* flags for heap insert and multi insert */
#define XLH_INSERT_ALL_VISIBLE_CLEARED
#define XLH_INSERT_LAST_MULTI_INSERT
#define XLH_INSERT_IS_SPECULATIVE
#define XLH_INSERT_CONTAINS_NEW_TUPLE

/* flags for update */
#define XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED
#define XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED
#define XLH_UPDATE_CONTAINS_OLD_TUPLE
#define XLH_UPDATE_CONTAINS_OLD_KEY
#define XLH_UPDATE_CONTAINS_NEW_TUPLE
#define XLH_UPDATE_PREFIX_FROM_OLD
#define XLH_UPDATE_SUFFIX_FROM_OLD

/* flags for delete */
#define XLH_DELETE_ALL_VISIBLE_CLEARED
#define XLH_DELETE_CONTAINS_OLD_TUPLE
#define XLH_DELETE_CONTAINS_OLD_KEY

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-20 Thread Peter Geoghegan
On Sun, Apr 19, 2015 at 9:37 PM, Peter Geoghegan p...@heroku.com wrote:
 Attached patch, V3.4, implements what I believe you and Heikki have in
 mind here.

Any plans to look at this, Svenne? You are signed up as a reviewer on
the commitfest app. A review of the documentation, and interactions
with other features like inheritance, updatable views and postgres_fdw
would be useful at this point. Obviously I've gone to a lot of effort
to document how things fit together at a high level on the UPSERT wiki
page, but these aspects have not been commented on all that much.

Thanks
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-17 Thread Stephen Frost
Dean,

* Dean Rasheed (dean.a.rash...@gmail.com) wrote:
 In all of this, I think we should try to keep things as simple as
 possible, to give the end user a chance to understand it --- although
 I'm not sure I've achieved that with my explanation :-)

Thanks a lot for this.  It goes along with my thinking also and matches,
I believe, what I had explained to Peter on our call.

Peter, please let me know if you agree.

Dean, I've been working through your patches over the past couple of
days (apologies for the lack of updates, just been busy) and hope to
push them very shortly (ie: by the end of the weekend).

One thing that I was hoping to discuss a bit is that I've gone ahead and
added another set of hooks, so we can have both permissive and
restrictive policies be provided from the hook.  It's a bit late to
make the grammar and other changes which would be required to add a
restrictive policy option to the built-in RLS, but adding the hooks is
relatively low-impact.

I'm also going to be including a test_rls_hooks module into
src/test/modules which will test those hooks and provide an example of
how to use them.

As for the discussion- there was some concern raised about extensions
being able to override built-in policies by using the hooks a certain
way.  I don't entirely follow the logic behind that concern as an
extension has the ability to read the files on disk directly from C
code, should it be written to do so, and so not providing a hook to add
permissive policies is denying useful functionality for very question
gain, in my view at least.

Thoughts?

Thanks!

Stephen


signature.asc
Description: Digital signature


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-16 Thread Andres Freund
On 2015-04-15 17:58:54 +0300, Heikki Linnakangas wrote:
 When the speculative insertion is finished, write a new kind of a WAL record
 for that. The record only needs to contain the ctid of the tuple. Replaying
 that record will clear the flag on the heap tuple that said that it was a
 speculative insertion.

 In logical decoding, decode speculative insertions like any other insertion.
 To decode a super-deletion record, scan the reorder buffer for the
 transaction to find the corresponding speculative insertion record for the
 tuple, and remove it.

 BTW, that'd work just as well without the new WAL record to finish a
 speculative insertion. Am I missing something?

I'm, completely independent of logical decoding, of the *VERY* strong
opinion that 'speculative insertions' should never be visible when
looking with normal snapshots. For one it allows to simplify
considerations around wraparound (which has proven to be a very good
idea, c.f. multixacts + vacuum causing data corruption years after it
was thought to be harmless). For another it allows to reclaim/redefine
the bit after a database restart/upgrade. Given how complex this is and
how scarce flags are that seems like a really good property.

And avoiding those flags to be visible to the outside requires a WAL
record, otherwise it won't be correct on the standby.

Andres


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-16 Thread Andres Freund
On 2015-04-15 18:53:15 +0300, Heikki Linnakangas wrote:
 Hmm, ok, I've read the INSERT ... ON CONFLICT UPDATE and logical decoding
 thread now, and I have to say that IMHO it's a lot more sane to handle this
 in ReorderBufferCommit() like Peter first did, than to make the main
 insertion path more complex like this.

I don't like Peter's way much. For one it's just broken. For another
it's quite annoying to trigger disk reads to figure out what actual type
of record something is.

If we go that way that's the way I think it should be done: Whenever we
encounter a speculative record we 'unlink' it from the changes that will
be reused for spooling from disk and do nothing further. Then we just
continue reading through the records. If the next thing we encounter is
a super-deletion we throw away that record. If it's another type of
change (or even bettter a 'speculative insertion succeeded' record)
insert it. That'll still require some uglyness, but it should not be too
bad.

I earlier thought that'd not be ok because there could be a new catalog
snapshot inbetween, but I was mistaken: The locking on the source
transaction prevents problems.

 Another idea is to never spill the latest record to disk, at least if it was
 a speculative insertion. Then you would be sure that when you see the
 super-deletion record, the speculative insertion it refers to is still in
 memory. That seems simple.

It's not guaranteed to be the last record, there can be records
inbetween (snapshots from other backends at the very least).


Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-16 Thread Peter Geoghegan
On Thu, Apr 16, 2015 at 2:23 AM, Andres Freund and...@anarazel.de wrote:
 I'm, completely independent of logical decoding, of the *VERY* strong
 opinion that 'speculative insertions' should never be visible when
 looking with normal snapshots. For one it allows to simplify
 considerations around wraparound (which has proven to be a very good
 idea, c.f. multixacts + vacuum causing data corruption years after it
 was thought to be harmless). For another it allows to reclaim/redefine
 the bit after a database restart/upgrade. Given how complex this is and
 how scarce flags are that seems like a really good property.

 And avoiding those flags to be visible to the outside requires a WAL
 record, otherwise it won't be correct on the standby.

I'm a bit distracted here, and not sure exactly what you mean. What's
a normal snapshot?

Do you just mean that you think that speculative insertions should be
explicitly affirmed by a second record (making it not a speculative
tuple, but rather, a fully fledged tuple)? IOW, an MVCC snapshot has
no chance of seeing a tuple until it was affirmed by a second in-place
modification, regardless of tuple xmin xact commit status?

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-16 Thread Heikki Linnakangas

On 04/16/2015 12:18 PM, Andres Freund wrote:

On 2015-04-15 18:53:15 +0300, Heikki Linnakangas wrote:

Hmm, ok, I've read the INSERT ... ON CONFLICT UPDATE and logical decoding
thread now, and I have to say that IMHO it's a lot more sane to handle this
in ReorderBufferCommit() like Peter first did, than to make the main
insertion path more complex like this.


I don't like Peter's way much. For one it's just broken. For another
it's quite annoying to trigger disk reads to figure out what actual type
of record something is.

If we go that way that's the way I think it should be done: Whenever we
encounter a speculative record we 'unlink' it from the changes that will
be reused for spooling from disk and do nothing further. Then we just
continue reading through the records. If the next thing we encounter is
a super-deletion we throw away that record. If it's another type of
change (or even bettter a 'speculative insertion succeeded' record)
insert it. That'll still require some uglyness, but it should not be too
bad.


Sounds good to me.

- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-16 Thread Peter Geoghegan
On Thu, Apr 16, 2015 at 2:18 AM, Andres Freund and...@anarazel.de wrote:
 On 2015-04-15 18:53:15 +0300, Heikki Linnakangas wrote:
 Hmm, ok, I've read the INSERT ... ON CONFLICT UPDATE and logical decoding
 thread now, and I have to say that IMHO it's a lot more sane to handle this
 in ReorderBufferCommit() like Peter first did, than to make the main
 insertion path more complex like this.

 I don't like Peter's way much. For one it's just broken. For another
 it's quite annoying to trigger disk reads to figure out what actual type
 of record something is.

 If we go that way that's the way I think it should be done: Whenever we
 encounter a speculative record we 'unlink' it from the changes that will
 be reused for spooling from disk and do nothing further. Then we just
 continue reading through the records.

You mean we continue iterating through *changes* from ReorderBufferCommit()?

 If the next thing we encounter is
 a super-deletion we throw away that record. If it's another type of
 change (or even bettter a 'speculative insertion succeeded' record)
 insert it.

By insert it, I gather you mean report to the the logical decoding
plugin as an insert change.

 That'll still require some uglyness, but it should not be too
 bad.

So, to be clear, what you have in mind is sort of a hybrid between my
first and second approaches (mostly my first approach).

We'd have coordination between records originally decoded into
changes, maybe intercepting them during xact reassembly, like my
first approach. We'd mostly do the same thing as the first approach,
actually. The major difference would be that there'd be explicit
speculative affirmation WAL records. But we wouldn't rely on those
affirmation records within ReorderBufferCommit() - we'd rely on the
*absence* of a super deletion WAL record (to report an insert change
to the decoding plugin). To emphasize, like my first approach, it
would be based on an *absence* of a super deletion WAL record.

However, like my second approach, there would be a speculative
affirmation WAL record. The new speculative affirmation WAL record
would however be quite different to what my second approach to logical
decoding (the in-place update record thing that was in V3.3) actually
did. In particular, it would be far more simple, and the tuple would
be built from the original insertion record within logical decoding.

Right now, I'm tired, so bear with me. What I think I'm not quite
getting here is how the new type of affirmation record affects
visibility (or anything else, actually). Clearly dirty snapshots need
to see the record to set a speculative insertion token for their
caller to wait on (and HeapTupleSatisfiesVacuum() cannot see the
speculatively inserted tuple as reclaimable, of course). They need
this *before* the speculative insertion is affirmed, of course.

Maybe you mean: If the speculative insertion xact is in progress, then
the tuple is visible to several types of snapshots (dirty, vacuum,
self, any). If it is not, then tuples are not visible because they are
only speculative (and not *confirmed*). If they were confirmed, and
the xact was committed, then those tuples are logically and physically
indistinguishable from tuples that were inserted in the ordinary
manner.

Is that it? Basically, the affirmation records have nothing much to do
with logical decoding in particular. But you still need to super
delete, so that several types of snapshots ((dirty, vacuum, self, any)
*stop* seeing the tuple as visible independent of the inserting xact
being in progress.

 I earlier thought that'd not be ok because there could be a new catalog
 snapshot inbetween, but I was mistaken: The locking on the source
 transaction prevents problems.

I thought this was the case.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-15 Thread Heikki Linnakangas

On 04/15/2015 07:51 AM, Peter Geoghegan wrote:

+heap_finish_speculative(Relation relation, HeapTuple tuple, bool conflict)
+{
+   if (!conflict)
+   {
+   /*
+* Update the tuple in-place, in the common case where no 
conflict was
+* detected during speculative insertion.
+*
+* When heap_insert is called in respect of a speculative 
tuple, the
+* page will actually have a tuple inserted.  However, during 
recovery
+* replay will add an all-zero tuple to the page instead, which 
is the
+* same length as the original (but the tuple header is still 
WAL
+* logged and will still be restored at that point).  If and 
when the
+* in-place update record corresponding to releasing a value 
lock is
+* replayed, crash recovery takes the final tuple value from 
there.
+* Thus, speculative heap records require two WAL records.
+*
+* Logical decoding interprets an in-place update associated 
with a
+* speculative insertion as a regular insert change.  In other 
words,
+* the in-place record generated affirms that a speculative 
insertion
+* completed successfully.
+*/
+   heap_inplace_update(relation, tuple);
+   }
+   else
+   {


That's a bizarre solution. May I suggest a much simpler one:

Make the heap-insert record the same for normal and speculative 
insertions, except for a flag that's set if it's a speculative one. 
Replay as usual.


When the speculative insertion is finished, write a new kind of a WAL 
record for that. The record only needs to contain the ctid of the tuple. 
Replaying that record will clear the flag on the heap tuple that said 
that it was a speculative insertion.


In logical decoding, decode speculative insertions like any other 
insertion. To decode a super-deletion record, scan the reorder buffer 
for the transaction to find the corresponding speculative insertion 
record for the tuple, and remove it.


BTW, that'd work just as well without the new WAL record to finish a 
speculative insertion. Am I missing something?



--- a/src/include/storage/off.h
+++ b/src/include/storage/off.h
@@ -26,6 +26,7 @@ typedef uint16 OffsetNumber;
 #define InvalidOffsetNumber((OffsetNumber) 0)
 #define FirstOffsetNumber  ((OffsetNumber) 1)
 #define MaxOffsetNumber((OffsetNumber) (BLCKSZ / 
sizeof(ItemIdData)))
+#define MagicOffsetNumber  (MaxOffsetNumber + 1)
 #define OffsetNumberMask   (0x)/* valid uint16 
bits */


IMHO it would be nicer if the magic value was more constant, e.g. 0x 
or 0xfffe, instead of basing it on MaxOffsetNumber which depends on 
block size. I would rather not include MaxOffsetNumber of anything 
derived from it in the on-disk dormat.


- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-15 Thread Andres Freund
On 2015-04-15 17:58:54 +0300, Heikki Linnakangas wrote:
 On 04/15/2015 07:51 AM, Peter Geoghegan wrote:
 +heap_finish_speculative(Relation relation, HeapTuple tuple, bool conflict)
 +{
 +if (!conflict)
 +{
 +/*
 + * Update the tuple in-place, in the common case where no 
 conflict was
 + * detected during speculative insertion.
 + *
 + * When heap_insert is called in respect of a speculative 
 tuple, the
 + * page will actually have a tuple inserted.  However, during 
 recovery
 + * replay will add an all-zero tuple to the page instead, which 
 is the
 + * same length as the original (but the tuple header is still 
 WAL
 + * logged and will still be restored at that point).  If and 
 when the
 + * in-place update record corresponding to releasing a value 
 lock is
 + * replayed, crash recovery takes the final tuple value from 
 there.
 + * Thus, speculative heap records require two WAL records.
 + *
 + * Logical decoding interprets an in-place update associated 
 with a
 + * speculative insertion as a regular insert change.  In other 
 words,
 + * the in-place record generated affirms that a speculative 
 insertion
 + * completed successfully.
 + */
 +heap_inplace_update(relation, tuple);
 +}
 +else
 +{
 
 That's a bizarre solution.

I tend to agree, but for different reasons.

 In logical decoding, decode speculative insertions like any other insertion.
 To decode a super-deletion record, scan the reorder buffer for the
 transaction to find the corresponding speculative insertion record for the
 tuple, and remove it.

Not that easy. That buffer is spilled to disk and such. As discussed.

Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-15 Thread Heikki Linnakangas

On 04/15/2015 06:01 PM, Andres Freund wrote:

On 2015-04-15 17:58:54 +0300, Heikki Linnakangas wrote:

On 04/15/2015 07:51 AM, Peter Geoghegan wrote:

+heap_finish_speculative(Relation relation, HeapTuple tuple, bool conflict)
+{
+   if (!conflict)
+   {
+   /*
+* Update the tuple in-place, in the common case where no 
conflict was
+* detected during speculative insertion.
+*
+* When heap_insert is called in respect of a speculative 
tuple, the
+* page will actually have a tuple inserted.  However, during 
recovery
+* replay will add an all-zero tuple to the page instead, which 
is the
+* same length as the original (but the tuple header is still 
WAL
+* logged and will still be restored at that point).  If and 
when the
+* in-place update record corresponding to releasing a value 
lock is
+* replayed, crash recovery takes the final tuple value from 
there.
+* Thus, speculative heap records require two WAL records.
+*
+* Logical decoding interprets an in-place update associated 
with a
+* speculative insertion as a regular insert change.  In other 
words,
+* the in-place record generated affirms that a speculative 
insertion
+* completed successfully.
+*/
+   heap_inplace_update(relation, tuple);
+   }
+   else
+   {


That's a bizarre solution.


I tend to agree, but for different reasons.


In logical decoding, decode speculative insertions like any other insertion.
To decode a super-deletion record, scan the reorder buffer for the
transaction to find the corresponding speculative insertion record for the
tuple, and remove it.


Not that easy. That buffer is spilled to disk and such. As discussed.


Hmm, ok, I've read the INSERT ... ON CONFLICT UPDATE and logical 
decoding thread now, and I have to say that IMHO it's a lot more sane 
to handle this in ReorderBufferCommit() like Peter first did, than to 
make the main insertion path more complex like this.


Another idea is to never spill the latest record to disk, at least if it 
was a speculative insertion. Then you would be sure that when you see 
the super-deletion record, the speculative insertion it refers to is 
still in memory. That seems simple.


- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-09 Thread Peter Geoghegan
On Wed, Mar 18, 2015 at 2:59 AM, Dean Rasheed dean.a.rash...@gmail.com wrote:
 Yes, I read that, and I agree with the intention to not leak data
 according to both the INSERT and UPDATE policies, however...

 You're seeing a failure that applies to the target tuple of the UPDATE
 (the tuple that we can't leak the contents of). I felt it was best to
 check all policies against the target/existing tuple, including both
 WITH CHECK OPTIONS and USING quals (which are both enforced).


 I think that's an incorrect implementation of the RLS UPDATE policy.
 The WITH CHECK quals of a RLS policy are intended to be applied to the
 NEW data, not the existing data. This patch is applying the WITH CHECK
 quals to both the existing and NEW tuples, which runs counter to the
 way RLS polices are normally enforced, and I think that will just lead
 to confusion.

The big idea (the fine details of which Stephen appeared to be in
tentative agreement with [1]) is that an UPSERT is a hybrid between an
INSERT and an UPDATE, and not simply an INSERT and separate UPDATE
tied together. So at the very least the exact behavior of such a
hybrid cannot be assumed to be any particular way just from
generalizing from known behaviors for INSERT and UPDATE (which is a
usability issue, since the fine details of RLS are already complex
enough without UPSERT).

The INSERT policies are only enforced when a tuple is inserted
because, when the alternative path isn't taken then it's really just
an INSERT.

For the UPDATE path, where the stickiness/hybridness begins, we
enforce the target tuple passes both INSERT policies, and UPDATE
policies (including USING quals as WCO). The theory here is that if
you're entitled to INSERT it, you ought to be entitled to INSERT the
existing tuple in order to take the UPDATE path. And we bunch the
UPDATE USING quals + WCO for the sake of (conceptual, not
implementation) simplicity - they're already all WCO at that point.

Finally, the final tuple (generated using the EXCLUDED and TARGET
tuples, from the UPDATE) must pass the UPDATE WCO (including any that
originated as USING quals, a distinction that no longer exists) as
well as INSERT policies. If you couldn't INSERT the tuple in the first
place (when there wasn't a conflict), then why should you be able to
UPSERT it? This is substantively the same row, no? You (the user)
are tacitly asserting that you don't care about whether the INSERT or
UPDATE path is taken anyway, so why should you care? Surely you'd want
this to fail as early as possible, rather than leaving it to chance. I
really do expect that people are only going to do simple
transformations in their UPDATE handler (e.g. ON CONFLICT UPDATE set
count = TARGET.count + EXCLUDED.count), so in practice it usually
doesn't matter.

Note that other systems that I looked at don't even support RLS with
SQL MERGE at all. So we have no precedent to consider that I'm aware
of, other than simply not supporting RLS, which would not be
outrageous IMV. I felt, given the ambiguity about how this should
differ from ordinary INSERTs + UPDATEs, that something quite
restrictive but not entirely restrictive (not supporting RLS, just
throwing an error all the time) was safest. In any case I doubt that
this will actually come up all that often.

 The problem with that is that the user will see errors saying that the
 data violates the RLS WITH CHECK policy, when they might quite
 reasonably argue that it doesn't. That's not really being
 conservative. I'd argue it's a bug.

Again, I accept that that's a valid interpretation of it. I have my
own opinion, but I will take the path of least resistance on this
point. What do other people think?

I'd appreciate it if you explicitly outlined what policies you feel
should be enforce at each of the 3 junctures within an UPSERT (post
INSERT, pre-UPDATE, post-UPDATE). I would also like you to be very
explicit about whether or not RLS WITH CHECK policies and USING quals
(presumably enforced as RLS WITH CHECK policies) from both INSERT and
UPDATE policies should be enforced at each point. In particular,
should I ever not treat RLS WCO and USING quals equivalently? (recall
that we don't want to elide an UPDATE silently, which makes much less
sense for UPSERT...I had assumed that whatever else, we'd always treat
WCO and USING quals from UPDATE (and ALL) policies equivalently, but
perhaps not).

Alternatively, perhaps you'd prefer to state your objection in terms
of the exact modifications you'd make to the above outline of the
existing behavior. I don't think I totally follow what you're saying
yet (which is the problem with being cleverer generally!). It is easy
to explain: The insert path is the same as always. Otherwise, both the
before and after tuple have all RLS policies (including USING quals)
enforced as WCOs. I think that it might be substantially easier to
explain that than to explain what you have in mind...let's see.

Thanks

[1] 

Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-08 Thread Peter Geoghegan
On Tue, Apr 7, 2015 at 10:59 PM, Peter Geoghegan p...@heroku.com wrote:
 The documentation has been updated to reflect all of this.

By the way, for the convenience of reviewers I continue to maintain a
mirror of pre-built documentation as outlined here:

https://wiki.postgresql.org/wiki/UPSERT#Documentation

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-04-07 Thread Peter Geoghegan
On Mon, Mar 30, 2015 at 9:20 AM, Peter Geoghegan p...@heroku.com wrote:
 * The code uses LockTupleExclusive to lock rows. That means the fkey key
   locking doesn't work; That's annoying. This means that using upsert
   will potentially cause deadlocks in other sessions :(. I think you'll
   have to determine what lock to acquire by fetching the tuple, doing
   the key comparison, and acquire the appropriate lock. That should be
   fine.

 Looking into the implementation of this. As we discussed, the
 difficulty about avoiding a lock escalation within ExecUpdate() is
 that we must fetch the row, run EvalPlanQual() to check if the new row
 version generated by updating will require a LockTupleExclusive or
 LockTupleNoKeyExclusive, and then lock the row using the right
 lockmode, and only then call ExecUpdate(). Right now, UPSERT benefits
 from fetching and locking the row together, so going this way imposes
 a little additional complexity. It's probably worth it, though.

Why do you think deadlocks will be a particular concern? Sure, it
could make the difference between deadlocking and not deadlocking,
which is bad, but it's not obvious to me that the risk would be any
worse than the risk of deadlocking with FKs in 9.2. Is that really all
that bad?


-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-31 Thread Heikki Linnakangas

On 03/30/2015 07:20 PM, Peter Geoghegan wrote:



* I think we should decouple the insertion and wal logging more. I think
   the promise tuple insertion should be different from the final
   insertion of the actual tuple. For one it seems cleaner to me, for
   another it will avoid the uglyness around logical decoding. I think
   also that the separation will make it more realistic to use something
   like this for a COPY variant that doesn't raise unique violations and
   such.

Your COPY argument swung this for me. I'm looking into the implementation.


I'm pretty sceptical of that. ISTM you'll need to do modify the page 
twice for each insertion, first to insert the promise tuple, and then to 
turn the promise tuple into a real tuple. And WAL-log both updates. 
That's going to hurt performance.


To recover COPY from unique violations, you can just do the same as 
INSERT ON CONFLICT IGNORE does, and super-delete the inserted tuple on 
conflict. To recover from any random error, you'll need to abort the 
(sub)transaction anyway, and I don't see how it helps to separate the 
insertion of the promise tuple and the finalization of the insertion.


- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-31 Thread Peter Geoghegan
On Tue, Mar 31, 2015 at 2:26 PM, Peter Geoghegan p...@heroku.com wrote:
 Andres' wish to do things that way is at least partially motivated by
 having logical decoding just work.

I should add that there appears to be some need to terminate the loop
of speculative token waiting. By that I mean that since we're not
looking at the proc array to get a speculative token from
HeapTupleSatisfiesDirty() now, there is a livelock hazard. That goes
away when the speculative inserter cleans up after itself, as Andres
proposed. It would also go away if any speculative waiter cleaned up
after the inserter, which you suggested (that would be kind of
invasive to places like _bt_doinsert(), though). Finally, it would
also work if HeapTupleSatisfiesDirty() tested if the token was still
held directly, before reporting a speculative token, by for example
attempting to briefly acquire a ShareLock on the token (but that would
mean that the extra lock acquisition would be required unless and
until someone updated that originally-speculative tuple, in doing so
finally changing its t_ctid).

I think that we definitely have to do something like this, in any
case. Maybe just have SpeculativeTokenWait deal with the clean up is
cleanest, if we're not going to have inserters clean-up after
themselves immediately per Andres' suggestion.
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-31 Thread Peter Geoghegan
On Tue, Mar 31, 2015 at 1:09 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 I'm pretty sceptical of that. ISTM you'll need to do modify the page twice
 for each insertion, first to insert the promise tuple, and then to turn the
 promise tuple into a real tuple. And WAL-log both updates. That's going to
 hurt performance.


Andres' wish to do things that way is at least partially motivated by
having logical decoding just work. The co-ordination I'm currently
doing across changes within transaction reassembly is pretty ugly.
Andres has strongly suggested that it's broken, too, since a snapshot
change could occur between a speculative insertion and its super
deletion within transaction resassembly, thus invalidating the
assumption that the next change not being a super deletion means there
is no such super deletion change (i.e. the insert should be treated as
real).

Anyway, if we don't do this, we'll need to make sure my changes to
transaction reassembly are sound. Hopefully that's an easy fix.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-30 Thread Peter Geoghegan
On Sat, Mar 28, 2015 at 6:36 PM, Andres Freund and...@2ndquadrant.com wrote:
 Just had a longer chat with Peter about this patch.

It was a very useful chat. Thanks for making yourself available to do it.

 * Not a fan of the heap flags usage, the reusage seems sketch to me
 * Explain should show the arbiter index in text as well
 * AddUniqueSpeculative is a bad name, it should refer IndexInfo
 * Work on the ExecInsert() comments
 * Let's remove the planner choosing the cheapest arbiter index; it
   should do all.
 * s/infer_unique_index/infer_arbiter_index/

OK.

 * Not supporting inheritance properly makes me uncomfortable. I don't
   think users will think that's a acceptable/reasonable restriction.

I'll look into making the inference specification deduce a child relation index.

 * Let's not use t_ctid directly, but add a wrapper

We talked about a union. This seems quite doable.

 * The code uses LockTupleExclusive to lock rows. That means the fkey key
   locking doesn't work; That's annoying. This means that using upsert
   will potentially cause deadlocks in other sessions :(. I think you'll
   have to determine what lock to acquire by fetching the tuple, doing
   the key comparison, and acquire the appropriate lock. That should be
   fine.

Looking into the implementation of this. As we discussed, the
difficulty about avoiding a lock escalation within ExecUpdate() is
that we must fetch the row, run EvalPlanQual() to check if the new row
version generated by updating will require a LockTupleExclusive or
LockTupleNoKeyExclusive, and then lock the row using the right
lockmode, and only then call ExecUpdate(). Right now, UPSERT benefits
from fetching and locking the row together, so going this way imposes
a little additional complexity. It's probably worth it, though.

 * I think we should decouple the insertion and wal logging more. I think
   the promise tuple insertion should be different from the final
   insertion of the actual tuple. For one it seems cleaner to me, for
   another it will avoid the uglyness around logical decoding. I think
   also that the separation will make it more realistic to use something
   like this for a COPY variant that doesn't raise unique violations and
   such.

Your COPY argument swung this for me. I'm looking into the implementation.

 * We discussed the infererence and that it should just reuse (code,
   grammar, docs) the column specification from create index.

Agreed.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-28 Thread Andres Freund
Hi,

Just had a longer chat with Peter about this patch.

* Not a fan of the heap flags usage, the reusage seems sketch to me
* Explain should show the arbiter index in text as well
* AddUniqueSpeculative is a bad name, it should refer IndexInfo
* Work on the ExecInsert() comments
* Let's remove the planner choosing the cheapest arbiter index; it
  should do all.
* s/infer_unique_index/infer_arbiter_index/
* Not supporting inheritance properly makes me uncomfortable. I don't
  think users will think that's a acceptable/reasonable restriction.
* Let's not use t_ctid directly, but add a wrapper
* The code uses LockTupleExclusive to lock rows. That means the fkey key
  locking doesn't work; That's annoying. This means that using upsert
  will potentially cause deadlocks in other sessions :(. I think you'll
  have to determine what lock to acquire by fetching the tuple, doing
  the key comparison, and acquire the appropriate lock. That should be
  fine.
* I think we should decouple the insertion and wal logging more. I think
  the promise tuple insertion should be different from the final
  insertion of the actual tuple. For one it seems cleaner to me, for
  another it will avoid the uglyness around logical decoding. I think
  also that the separation will make it more realistic to use something
  like this for a COPY variant that doesn't raise unique violations and
  such.
* We discussed the infererence and that it should just reuse (code,
  grammar, docs) the column specification from create index.
* Some more stuff I don't recall.


Greetings,

Andres Freund

-- 
 Andres Freund http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training  Services


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-26 Thread Gavin Flower

On 27/03/15 09:14, Peter Geoghegan wrote:

On Thu, Mar 26, 2015 at 2:51 PM, Heikki Linnakangas hlinn...@iki.fi wrote:

[...]

Oops - You're right. I find it interesting that this didn't result in
breaking my test cases.


[...]

Reminds of the situation where I got an A++ for a COBOL programming 
assignment that successfully handled the test data provided - then I 
found a major bug when 'idly' reviewing my code!  The lecturer (also a 
highly experienced developer) was amused when I pointed it out to her, 
and she said I still deserved the A++!



Cheers,
Gavin


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-26 Thread Heikki Linnakangas

On 03/26/2015 08:00 PM, Peter Geoghegan wrote:

On Wed, Mar 25, 2015 at 12:42 PM, Peter Geoghegan p...@heroku.com wrote:

My next revision will have a more polished version of this scheme. I'm
not going to immediately act on Robert's feedback elsewhere (although
I'd like to), owing to time constraints - no reason to deny you the
opportunity to review the entirely unrelated low-level speculative
locking mechanism due to that.


Attached revision, V3.1, implements this slightly different way of
figuring out if an insertion is speculative, as discussed. We reuse
t_ctid for speculatively inserted tuples. That's where the counter
goes. I think that this is a significant improvement, since there is
no longer any need to touch the proc array for any reason, without
there being any significant disadvantage that I'm aware of. I also
fixed some bitrot, and a bug with index costing (the details aren't
terribly interesting - tuple width wasn't being calculated correctly).


Cool. Quickly looking at the patch though - does it actually work as it 
is? RelationPutHeapTuple will overwrite the ctid field when the tuple is 
put on the page, so I don't think the correct token will make it to disk 
as the patch stands. Also, there are a few places where we currently 
check if t_ctid equals the tuple's location, and try to follow t_ctid if 
it doesn't. I think those need to be taught that t_ctid can also be a token.


- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-26 Thread Peter Geoghegan
On Thu, Mar 26, 2015 at 2:51 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 Attached revision, V3.1, implements this slightly different way of
 figuring out if an insertion is speculative, as discussed. We reuse
 t_ctid for speculatively inserted tuples. That's where the counter
 goes. I think that this is a significant improvement, since there is
 no longer any need to touch the proc array for any reason, without
 there being any significant disadvantage that I'm aware of. I also
 fixed some bitrot, and a bug with index costing (the details aren't
 terribly interesting - tuple width wasn't being calculated correctly).

 Cool. Quickly looking at the patch though - does it actually work as it is?

The test cases pass, including jjanes_upsert, and stress tests that
test for unprincipled deadlocks. But yes, I am entirely willing to
believe that something that was written in such haste could be broken.
My manual testing was pretty minimal.

Sorry for posting a shoddy patch, but I thought it was more important
to show you that this is perfectly workable ASAP.

 RelationPutHeapTuple will overwrite the ctid field when the tuple is put on
 the page, so I don't think the correct token will make it to disk as the
 patch stands.

Oops - You're right. I find it interesting that this didn't result in
breaking my test cases. I guess that not having proc array locking
might have made the difference with unprincipled deadlocks, which I
could not recreate (and row locking saves us from breaking UPSERT, I
think - although if so the token lock would still certainly be needed
for the IGNORE variant). It is interesting that this wasn't obviously
broken for UPSERT, though. I think it at least suggests that when
testing, we need to be more careful with taking a working UPSERT as a
proxy for a working ON CONFLICT IGNORE.

 Also, there are a few places where we currently check if
 t_ctid equals the tuple's location, and try to follow t_ctid if it doesn't.
 I think those need to be taught that t_ctid can also be a token.

I did fix at least some of those. I thought that the choke point for
doing that was fairly small, entirely confined to one or two routines
with heapam.c. But it would surely be better to follow your suggestion
of using an invalid/magic tuple offset value to be sure that it cannot
possibly occur elsewhere. And I'm still using that infomask2 bit,
which is probably not really necessary. So that needs to change too.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-25 Thread Peter Geoghegan
On Wed, Mar 18, 2015 at 2:41 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 Here's what I had in mind: the inserter tags the tuple with the speculative
 insertion token, by storing the token in the t_ctid field. If the inserter
 needs to super-delete the tuple, it sets xmax like in a regular deletion,
 but also sets another flag to indicate that it was a super-deletion.

I was able to quickly hack up a prototype of this in my hotel room at
pgConf.US. It works fine at first blush, passing the jjanes_upsert
stress tests and my own regression tests without a problem. Obviously
it needs more testing and clean-up before posting, but I was pleased
with how easy this was.

 When another backend inserts, and notices that it has a potential conflict
 with the first tuple, it tries to acquire a hw-lock on the token. In most
 cases, the inserter has long since completed the insertion, and the
 acquisition succeeds immediately but you have to check because the token is
 not cleared on a completed insertion.

You don't even have to check/take a ShareLock on the token when the
other xact committed/aborted, because you know that if it is there,
then based on that (and based on the fact that it wasn't super
deleted) the tuple is visible/committed, or (in the event of
other-xact-abort) not visible/aborted. In other words, we continue to
only check for a speculative token when the inserting xact is in
flight - we just take the token from the heap now instead. Not much
needs to change, AFAICT.

 Regarding the physical layout: We can use a magic OffsetNumber value above
 MaxOffsetNumber to indicate that the t_ctid field stores a token rather than
 a regular ctid value. And another magic t_ctid value to indicate that a
 tuple has been super-deleted. The token and the super-deletion flag are
 quite ephemeral, they are not needed after the inserting transaction has
 completed, so it's nice to not consume the valuable infomask bits for these
 things. Those states are conveniently not possible on an updated tuple, when
 we would need the t_ctid field for it's current purpose.

Haven't done anything about this yet. I'm just using an infomask2 bit
for now. Although that was only because I forgot that you suggested
this before having a go at implementing this new t_ctid scheme!

My next revision will have a more polished version of this scheme. I'm
not going to immediately act on Robert's feedback elsewhere (although
I'd like to), owing to time constraints - no reason to deny you the
opportunity to review the entirely unrelated low-level speculative
locking mechanism due to that.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-23 Thread Peter Geoghegan
On Thu, Mar 19, 2015 at 1:02 PM, Robert Haas robertmh...@gmail.com wrote:
 I think this is pretty lousy.  The reasons why the user wants things
 that way is because they created a UNIQUE index and it got bloated
 somehow with lots of dead tuples.  So they made a new UNIQUE index on
 the same column and then they're planning to do a DROP INDEX
 CONCURRENTLY on the old one, which is maybe even now in progress.  And
 now they start getting duplicate key failures, the avoidance of which
 was their whole reason for using UPSERT in the first place.  If I were
 that user, I'd report that as a bug, and if someone told me that it
 was intended behavior, I'd say oh, so you deliberately designed this
 feature to not work some of the time?.

 ISTM that we need to (1) decide which operator we're using to compare
 and then (2) tolerate conflicts in every index that uses that
 operator.  In most cases there will only be one, but if there are
 more, so be it.


On reflection, I see your point. I'll try and do something about this too.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-18 Thread Dean Rasheed
On 17 March 2015 at 23:25, Peter Geoghegan p...@heroku.com wrote:
 Possibly I'm missing something though.

 I think that you may have. Did you read the commit message/docs of the
 RLS commit 0004-*? You must consider the second point here, I believe:

 
 The 3 places that RLS policies are enforced are:

 * Against row actually inserted, after insertion proceeds successfully
   (INSERT-applicable policies only).

 * Against row in target table that caused conflict.  The implementation
   is careful not to leak the contents of that row in diagnostic
   messages (INSERT-applicable *and* UPDATE-applicable policies).

 * Against the version of the row added by to the relation after
   ExecUpdate() is called (INSERT-applicable *and* UPDATE-applicable
   policies).

 


Yes, I read that, and I agree with the intention to not leak data
according to both the INSERT and UPDATE policies, however...

 You're seeing a failure that applies to the target tuple of the UPDATE
 (the tuple that we can't leak the contents of). I felt it was best to
 check all policies against the target/existing tuple, including both
 WITH CHECK OPTIONS and USING quals (which are both enforced).


I think that's an incorrect implementation of the RLS UPDATE policy.
The WITH CHECK quals of a RLS policy are intended to be applied to the
NEW data, not the existing data. This patch is applying the WITH CHECK
quals to both the existing and NEW tuples, which runs counter to the
way RLS polices are normally enforced, and I think that will just lead
to confusion.

 I can see why you might not like that behavior, but it is the intended
 behavior. I thought that this whole intersection of RLS + UPSERT is
 complex enough that it would be best to be almost as conservative as
 possible in what fails and what succeeds. The one exception is when
 the insert path is actually taken, since the statement is an INSERT
 statement.

The problem with that is that the user will see errors saying that the
data violates the RLS WITH CHECK policy, when they might quite
reasonably argue that it doesn't. That's not really being
conservative. I'd argue it's a bug.

Regards,
Dean


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-18 Thread Robert Haas
On Tue, Mar 17, 2015 at 6:27 PM, Peter Geoghegan p...@heroku.com wrote:
 On Tue, Mar 17, 2015 at 12:11 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 I'm still not sure the way the speculative locking works is the best
 approach. Instead of clearing xmin on super-deletion, a new flag on the heap
 tuple seems more straightforward. And we could put the speculative insertion
 token in t_ctid, instead of stashing it in the PGPROC array. That would
 again seem more straightforward.

 I see the appeal of that approach. What concerns me about that
 approach is that it makes it the problem of the inserter to confirm
 its insertion, even though overwhelmingly, speculative insertions
 succeeds (the race window is small due to the pre-check). The current
 speculative token is legitimately a very short lived thing, a thing
 that I hesitate to write to disk at all. So our optimistic approach to
 inserting speculatively loses its optimism, which I don't like, if you
 know what I mean.

Modifying a shared buffer is not the same as writing to disk.

 If I'm reading this correctly, if there are multiple indexes that match the
 unique index inference specification, we pick the cheapest one. Isn't that
 unstable? Two backends running the same INSERT ON CONFLICT statement might
 pick different indexes, and the decision might change over time as the table
 is analyzed. I think we should have a more robust rule. Could we easily just
 use all matching indexes?

 Robert feel pretty strongly that there should be a costing aspect to
 this. Initially I was skeptical of this, but just did what he said all
 the same. But I've since come around to his view entirely because we
 now support partial unique indexes.

I think Heikki's concern is something different, although I am not
altogether up to speed on this and may be confused.  The issue is:
suppose that process A and process B are both furiously upserting into
the same table with the same key column but, because they have
different costing parameters, process A consistently chooses index X
and process B consistently chooses index Y.  In that situation, will
we deadlock, livelock, error out, bloat, or get any other undesirable
behavior, or is that A-OK?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-18 Thread Robert Haas
On Tue, Mar 17, 2015 at 3:11 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 I've been thinking that it would be nice to be able to specify a constraint
 name. Naming an index directly feels wrong, as in relational and SQL
 philosophy, indexes are just an implementation detail, but naming a
 constraint is a fair game. It would also be nice to be able to specify use
 the primary key.

Intuitively, I think you should specify an operator name, not a
constraint name.  That's what we do for, e.g., exclusion constraints,
and it feels right.  People sometimes create and drop indexes (and
thus, perhaps, the constraints that depend on them) for maintenance
reasons where a change in semantics will be unwelcome.  But I don't
accept Peter's argument that it's OK to be indifferent to which
particular equality semantics are being used.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-18 Thread Peter Geoghegan
On Wed, Mar 18, 2015 at 11:41 AM, Heikki Linnakangas hlinn...@iki.fi wrote:
 AFAICS, there is no need to go and clear the tag after the insert has
 completed.

 Here's what I had in mind: the inserter tags the tuple with the speculative
 insertion token, by storing the token in the t_ctid field. If the inserter
 needs to super-delete the tuple, it sets xmax like in a regular deletion,
 but also sets another flag to indicate that it was a super-deletion.

 When another backend inserts, and notices that it has a potential conflict
 with the first tuple, it tries to acquire a hw-lock on the token. In most
 cases, the inserter has long since completed the insertion, and the
 acquisition succeeds immediately but you have to check because the token is
 not cleared on a completed insertion. It would be slightly faster for the
 second backend if the inserter actually removed the token after the
 insertion has completed: it wouldn't need to check the lock if the tuple was
 not tagged in the first place. But that'd be just a tiny optimization, for
 the rare case that there is a conflict, and surely not worth it.

 Hmm, I just realized a little fly in that ointment: if the inserter inserts
 enough tuples to wrap around the token counter (4 billion?) in a single
 transaction, another backend that inserts could confuse a new speculative
 insertion with one that completed a long time ago. The risk seems small
 enough that we could just accept it. I don't think anything particularly bad
 would happen on a false positive here. Or we could also use all 48 bits
 available in the t_ctid to push it truly in the realm of ain't-gonna-happen.
 Or we could use (relfilenode, block,  token) as the lock tag for the
 SpeculativeInsertionLock.

Maybe we'd use all 48-bits anyway, but it's not a major concern either
way. Speculative token locks (by design) are only held for an instant.
I think a spurious wait would be entirely benign, and very unlikely.

 Regarding the physical layout: We can use a magic OffsetNumber value above
 MaxOffsetNumber to indicate that the t_ctid field stores a token rather than
 a regular ctid value. And another magic t_ctid value to indicate that a
 tuple has been super-deleted. The token and the super-deletion flag are
 quite ephemeral, they are not needed after the inserting transaction has
 completed, so it's nice to not consume the valuable infomask bits for these
 things. Those states are conveniently not possible on an updated tuple, when
 we would need the t_ctid field for it's current purpose.

You seem pretty convinced that this is the way to go. I'll try and
produce a revision that works this way shortly. I don't think that it
will be all that hard to come up with something to prove the idea out.

 I think Heikki's concern is something different, although I am not
 altogether up to speed on this and may be confused.  The issue is:
 suppose that process A and process B are both furiously upserting into
 the same table with the same key column but, because they have
 different costing parameters, process A consistently chooses index X
 and process B consistently chooses index Y.  In that situation, will
 we deadlock, livelock, error out, bloat, or get any other undesirable
 behavior, or is that A-OK?

 Right, that's what I had in mind.

Oh, I see. I totally failed to understand that that was the concern.

I think it'll be fine. The pre-check is going to look for a heap tuple
using one or the other of (say) a pair of equivalent indexes. We might
miss the heap tuple because we picked an index that had yet to have a
physical index tuple inserted, and then hit a conflict on optimistic
insertion (the second phase). But there is no reason to think that
that won't happen anyway. The ordering of operations isn't critical.

The one issue you might still have is a duplicate violation, because
you happened to infer the unique index that does not get to tolerate
unique violations as conflicts that can be recovered from (and there
was a race, which is unlikely). I don't really care about this,
though. You really are inferring one particular unique index, and for
reasons like this I think it would be a mistake to try to pretend that
the unique index is 100% an implementation detail. That's why I called
the new clause a unique index inference specification.

This hypothetical set of unique indexes will always have n-1 redundant
unique indexes - they must closely match. That's something that calls
into question why the user wants things this way to begin with. Also,
note that one unique index will consistently win, since the
insertion order is stable (the relcache puts them in OID order). So it
will not be all over the map.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-18 Thread Heikki Linnakangas

On 03/18/2015 06:23 PM, Robert Haas wrote:

On Tue, Mar 17, 2015 at 6:27 PM, Peter Geoghegan p...@heroku.com wrote:

On Tue, Mar 17, 2015 at 12:11 PM, Heikki Linnakangas hlinn...@iki.fi wrote:

I'm still not sure the way the speculative locking works is the best
approach. Instead of clearing xmin on super-deletion, a new flag on the heap
tuple seems more straightforward. And we could put the speculative insertion
token in t_ctid, instead of stashing it in the PGPROC array. That would
again seem more straightforward.


I see the appeal of that approach. What concerns me about that
approach is that it makes it the problem of the inserter to confirm
its insertion, even though overwhelmingly, speculative insertions
succeeds (the race window is small due to the pre-check). The current
speculative token is legitimately a very short lived thing, a thing
that I hesitate to write to disk at all. So our optimistic approach to
inserting speculatively loses its optimism, which I don't like, if you
know what I mean.


Modifying a shared buffer is not the same as writing to disk.


AFAICS, there is no need to go and clear the tag after the insert has 
completed.


Here's what I had in mind: the inserter tags the tuple with the 
speculative insertion token, by storing the token in the t_ctid field. 
If the inserter needs to super-delete the tuple, it sets xmax like in a 
regular deletion, but also sets another flag to indicate that it was a 
super-deletion.


When another backend inserts, and notices that it has a potential 
conflict with the first tuple, it tries to acquire a hw-lock on the 
token. In most cases, the inserter has long since completed the 
insertion, and the acquisition succeeds immediately but you have to 
check because the token is not cleared on a completed insertion. It 
would be slightly faster for the second backend if the inserter actually 
removed the token after the insertion has completed: it wouldn't need to 
check the lock if the tuple was not tagged in the first place. But 
that'd be just a tiny optimization, for the rare case that there is a 
conflict, and surely not worth it.


Hmm, I just realized a little fly in that ointment: if the inserter 
inserts enough tuples to wrap around the token counter (4 billion?) in a 
single transaction, another backend that inserts could confuse a new 
speculative insertion with one that completed a long time ago. The risk 
seems small enough that we could just accept it. I don't think anything 
particularly bad would happen on a false positive here. Or we could also 
use all 48 bits available in the t_ctid to push it truly in the realm of 
ain't-gonna-happen. Or we could use (relfilenode, block,  token) as the 
lock tag for the SpeculativeInsertionLock.


Regarding the physical layout: We can use a magic OffsetNumber value 
above MaxOffsetNumber to indicate that the t_ctid field stores a token 
rather than a regular ctid value. And another magic t_ctid value to 
indicate that a tuple has been super-deleted. The token and the 
super-deletion flag are quite ephemeral, they are not needed after the 
inserting transaction has completed, so it's nice to not consume the 
valuable infomask bits for these things. Those states are conveniently 
not possible on an updated tuple, when we would need the t_ctid field 
for it's current purpose.



If I'm reading this correctly, if there are multiple indexes that match the
unique index inference specification, we pick the cheapest one. Isn't that
unstable? Two backends running the same INSERT ON CONFLICT statement might
pick different indexes, and the decision might change over time as the table
is analyzed. I think we should have a more robust rule. Could we easily just
use all matching indexes?


Robert feel pretty strongly that there should be a costing aspect to
this. Initially I was skeptical of this, but just did what he said all
the same. But I've since come around to his view entirely because we
now support partial unique indexes.


I think Heikki's concern is something different, although I am not
altogether up to speed on this and may be confused.  The issue is:
suppose that process A and process B are both furiously upserting into
the same table with the same key column but, because they have
different costing parameters, process A consistently chooses index X
and process B consistently chooses index Y.  In that situation, will
we deadlock, livelock, error out, bloat, or get any other undesirable
behavior, or is that A-OK?


Right, that's what I had in mind.

- Heikki


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-18 Thread Peter Geoghegan
On Wed, Mar 18, 2015 at 9:19 AM, Robert Haas robertmh...@gmail.com wrote:
 On Tue, Mar 17, 2015 at 3:11 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 I've been thinking that it would be nice to be able to specify a constraint
 name. Naming an index directly feels wrong, as in relational and SQL
 philosophy, indexes are just an implementation detail, but naming a
 constraint is a fair game. It would also be nice to be able to specify use
 the primary key.

 Intuitively, I think you should specify an operator name, not a
 constraint name.  That's what we do for, e.g., exclusion constraints,
 and it feels right.  People sometimes create and drop indexes (and
 thus, perhaps, the constraints that depend on them) for maintenance
 reasons where a change in semantics will be unwelcome.

I think we should use a constraint name. That is the plain reality of
what we're doing, and is less ambiguous than an operator. 99% of the
time you'll be happy with an unspecified, across-the-board IGNORE, or
won't be using exclusion constraints anyway (so we can infer a unique
index).

A constraint name covers all reasonable cases, since partial unique
indexes are otherwise covered (partial unique indexes do not have a
pg_constraint entry). Oracle has a hint for ignoring particular, named
unique indexes (not constraints). I realize that Oracle hints are not
supposed to affect semantics, but this is actually true (Google it).
This is a bit ugly, but less ugly as the hint, since as Heikki points
out we're only naming a constraint. Naming a constraint reflects the
reality of how the feature needs to work, and has a sort of precedent
from other systems.

 But I don't
 accept Peter's argument that it's OK to be indifferent to which
 particular equality semantics are being used.

I am not suggesting actual indifference makes sense. I am leaving it
up to the definition of available indexes. And there are no known
cases where it could matter anyway, unless you consider the ===
operator for tuples to be a counter example. And you need multiple
conflicting unique indexes on the exact same attributes/expressions on
attributes to begin with. Isn't that a highly esoteric thing to have
to worry about? Perhaps to the extent that literally no one will ever
have to care anyway? It's an oddball use-case, if ever I saw one.

Note: the issue of caring about equality semantics across B-Tree
opclasses of the same type, and the issue of naming unique indexes are
separate issues, AFAICT. No one should confuse them. The only
crossover is that the oddball use-case mentioned could use the named
constraint thing as an escape hatch.

As I've said, I think it's misguided to try to make unique indexes
100% an implementation detail. It's going to fall apart in edge cases,
like the one with multiple unique indexes that I mentioned in my last
e-mail. No one thinks of them that way, including users.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-17 Thread Peter Geoghegan
On Mon, Mar 16, 2015 at 8:10 AM, Dean Rasheed dean.a.rash...@gmail.com wrote:
 (Note there is some bitrot in gram.y that prevents the first patch
 from applying cleanly to HEAD)

That's trivially fixable. I'll have those fixes in the next revision,
once I firm some things up with Heikki.

 I tested using the attached script, and one test didn't behave as I
 expected. I believe the following should have been a valid upsert
 (following the update path) but actually it failed:

 INSERT INTO t1 VALUES (4, 0) ON CONFLICT (a) UPDATE SET b = 1;

 AFAICT, it is applying a WITH CHECK OPTION with qual b  0 AND a % 2
 = 0 to the about-to-be-updated tuple (a=4, b=0), which is wrong
 because the b  0 check (policy p3) should only be applied to the
 post-update tuple.

 Possibly I'm missing something though.

I think that you may have. Did you read the commit message/docs of the
RLS commit 0004-*? You must consider the second point here, I believe:


The 3 places that RLS policies are enforced are:

* Against row actually inserted, after insertion proceeds successfully
  (INSERT-applicable policies only).

* Against row in target table that caused conflict.  The implementation
  is careful not to leak the contents of that row in diagnostic
  messages (INSERT-applicable *and* UPDATE-applicable policies).

* Against the version of the row added by to the relation after
  ExecUpdate() is called (INSERT-applicable *and* UPDATE-applicable
  policies).



You're seeing a failure that applies to the target tuple of the UPDATE
(the tuple that we can't leak the contents of). I felt it was best to
check all policies against the target/existing tuple, including both
WITH CHECK OPTIONS and USING quals (which are both enforced).

I can see why you might not like that behavior, but it is the intended
behavior. I thought that this whole intersection of RLS + UPSERT is
complex enough that it would be best to be almost as conservative as
possible in what fails and what succeeds. The one exception is when
the insert path is actually taken, since the statement is an INSERT
statement.
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-17 Thread Peter Geoghegan
On Tue, Mar 17, 2015 at 12:11 PM, Heikki Linnakangas hlinn...@iki.fi wrote:
 I'm still not sure the way the speculative locking works is the best
 approach. Instead of clearing xmin on super-deletion, a new flag on the heap
 tuple seems more straightforward. And we could put the speculative insertion
 token in t_ctid, instead of stashing it in the PGPROC array. That would
 again seem more straightforward.

I see the appeal of that approach. What concerns me about that
approach is that it makes it the problem of the inserter to confirm
its insertion, even though overwhelmingly, speculative insertions
succeeds (the race window is small due to the pre-check). The current
speculative token is legitimately a very short lived thing, a thing
that I hesitate to write to disk at all. So our optimistic approach to
inserting speculatively loses its optimism, which I don't like, if you
know what I mean.

OTOH, apart from avoiding stashing things in PGPROC, I do see another
advantage to what you outline. Doing things this way (and making the
insertion and confirmation of a speculative insertion a two-phased
thing) unambiguously fixes all problems with logical decoding, without
adding unexpected cross-change-coordination tricks during transaction
reassembly, and really without much further thought. All we do is get
a new case to decode, that ultimately produces a
REORDER_BUFFER_CHANGE_INSERT change, which Andres more or less wanted
to do anyway.

Under this scheme with using t_ctid, heap_insert() would do minimal
WAL logging, necessary for the same reasons that some WAL logging is
required within heap_lock_tuple() (so the new record type is very
similar to the existing, simple xl_heap_lock record type). We'd use
one of the two remaining bits within t_infomask2 for this, so that
waiters will know to interpret t_ctid as a speculative insertion token
(and then wait on it). Then, after speculative insertion succeeded,
we'd WAL log something closer to an UPDATE to confirm that insertion
was in fact successful, which is where the contents of the new tuple
is actually finally WAL-logged (like UPDATEs used to be, but without a
new tuple being WAL-logged at all, since there of course is none).

Is that more or less what you have in mind?

 A couple of quick random comments:

 /*
  * plan_speculative_use_index
  *  Use the planner to decide speculative insertion arbiter
 index
  *
  * Among indexes on target of INSERT ... ON CONFLICT, decide which index
 to
  * use to arbitrate taking alternative path.  This should be called
  * infrequently in practice, because it's unusual for more than one index
 to
  * be available that can satisfy a user-specified unique index inference
  * specification.
  *
  * Note: caller had better already hold some type of lock on the table.
  */
 Oid
 plan_speculative_use_index(PlannerInfo *root, List *indexList)
 {
 ...
 /* Locate cheapest IndexOptInfo for the target index */


 If I'm reading this correctly, if there are multiple indexes that match the
 unique index inference specification, we pick the cheapest one. Isn't that
 unstable? Two backends running the same INSERT ON CONFLICT statement might
 pick different indexes, and the decision might change over time as the table
 is analyzed. I think we should have a more robust rule. Could we easily just
 use all matching indexes?

Robert feel pretty strongly that there should be a costing aspect to
this. Initially I was skeptical of this, but just did what he said all
the same. But I've since come around to his view entirely because we
now support partial unique indexes.

You can add a predicate to a unique index inference specification, and
you're good, even if there is no partial index on those
attributes/expressions exactly matching the DML/inference predicate -
we use predicate_implied_by() for this, which works with an equivalent
non-partial unique index. This is because a non-partial unique index
covers those attributes sufficiently. There may be value in preferring
the cheap partial index, and then verifying that it actually did cover
the final inserted tuple version (which is how things work now). If we
cannot discriminate against one particular unique index, making sure
it covers the inserted heap tuple (by throwing a user-visible
ERRCODE_TRIGGERED_ACTION_EXCEPTION error if it doesn't, as I currently
do within ExecInsertIndexTuples()) is on shaky ground as a
user-visible behavior. I like that behavior, though - seems less
surprising than letting a failure to actually cover a selective
partial unique index predicate (that of the one and only arbiter
index) slide. You can only get this ERRCODE_TRIGGERED_ACTION_EXCEPTION
error when you actually had a predicate in your unique index inference
specification in the first place, so seems likely that you want the
error. But, I also like supporting unique indexes that are non-partial
even in the presence of a predicate in the unique index inference
specification clause, 

Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-17 Thread Heikki Linnakangas

On 03/05/2015 03:18 AM, Peter Geoghegan wrote:

Attached patch series forms what I'm calling V3.0 of the INSERT ... ON
CONFLICT IGNORE/UPDATE feature. (Sorry about all the threads. I feel
this development justifies a new thread, though.)


I'm still not sure the way the speculative locking works is the best 
approach. Instead of clearing xmin on super-deletion, a new flag on the 
heap tuple seems more straightforward. And we could put the speculative 
insertion token in t_ctid, instead of stashing it in the PGPROC array. 
That would again seem more straightforward.


A couple of quick random comments:


/*
 * plan_speculative_use_index
 *  Use the planner to decide speculative insertion arbiter index
 *
 * Among indexes on target of INSERT ... ON CONFLICT, decide which index to
 * use to arbitrate taking alternative path.  This should be called
 * infrequently in practice, because it's unusual for more than one index to
 * be available that can satisfy a user-specified unique index inference
 * specification.
 *
 * Note: caller had better already hold some type of lock on the table.
 */
Oid
plan_speculative_use_index(PlannerInfo *root, List *indexList)
{
...
/* Locate cheapest IndexOptInfo for the target index */


If I'm reading this correctly, if there are multiple indexes that match 
the unique index inference specification, we pick the cheapest one. 
Isn't that unstable? Two backends running the same INSERT ON CONFLICT 
statement might pick different indexes, and the decision might change 
over time as the table is analyzed. I think we should have a more robust 
rule. Could we easily just use all matching indexes?




... Deferred unique constraints are not supported as
+   arbiters of whether an alternative literalON CONFLICT/ path
+   should be taken.


We really need to find a shorter term for arbiter of whether an 
alternative path should be taken. Different variations of that term are 
used a lot, and it's tedious to read.



* There is still an unresolved semantics issue with unique index
inference and non-default opclasses. I think it's sufficient that the
available/defined unique indexes dictate our idea of a unique
violation (that necessitates taking the alternative path). Even in a
world where there exists a non-default opclass with an equals
operator that does not match that of the default opclass (that is not
really the world we live in, because the only counter-example known is
made that way specifically to *discourage* its use by users), this
seems okay to me. It seems okay to me because surely the relevant
definition of equality is the one actually chosen for the available
unique index. If there exists an ambiguity for some strange reason
(i.e. there are two unique indexes, on the same attribute(s), but with
different equals operators), then its a costing issue, so the
behavior given is essentially non-predictable (it could end up being
either...but hey, those are the semantics). I have a very hard time
imagining how that could ever be the case, even when we have (say)
case insensitive opclasses for the text type. A case insensitive
opclass is stricter than a case sensitive opclass.  Why would a user
ever want both on the same attribute(s) of the same table? Is the user
really more or less expecting to never get a unique violation on the
non-arbitrating unique index, despite all this?

If reviewers are absolutely insistent that this theoretical ambiguity
is a problem, we can add an optional CREATE INDEX style opclass
specification (I'm already using the IndexElems representation from
CREATE INDEX for the inference specification, actually, so that would
be easy enough). I really have a hard time believing that the ugliness
is a problem for those hypothetical users that eventually consider
equals operator ambiguity among opclasses among available unique
indexes to be a problem. I haven't just gone and implemented this
already because I didn't want to document that an opclass
specification will be accepted. Since there is literally no reason why
anyone would care today, I see no reason to add what IMV would really
just be cruft.


I've been thinking that it would be nice to be able to specify a 
constraint name. Naming an index directly feels wrong, as in relational 
and SQL philosophy, indexes are just an implementation detail, but 
naming a constraint is a fair game. It would also be nice to be able to 
specify use the primary key.


Attached patch contains a few more things I saw at a quick read.

- Heikki

diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml
index 46b8db8..d6fa98c 100644
--- a/doc/src/sgml/fdwhandler.sgml
+++ b/doc/src/sgml/fdwhandler.sgml
@@ -1014,6 +1014,10 @@ GetForeignServerByName(const char *name, bool missing_ok);
  source provides.
 /para
 
+!-- FIXME: If this is a hard limitation with the backend, the backend
+ should check and reject these cases. Otherwise, if it's possible
+ that a 

Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-17 Thread Peter Geoghegan
On Thu, Mar 5, 2015 at 3:44 PM, Peter Geoghegan p...@heroku.com wrote:
 Bruce Momjian kindly made available a server for stress-testing [1].
 I'm using jjanes_upsert for this task (I stopped doing this for a
 little while, and was in need of a new server).

BTW, this was run for about another week on Bruce's server, and no
further issues arose affecting either the B-Tree or exclusion
constraint implementations. I've stopped with it for now, because it
feels unlikely that I'm going to find any more bugs this way.

-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-16 Thread Dean Rasheed
On 5 March 2015 at 23:44, Peter Geoghegan p...@heroku.com wrote:
 On Wed, Mar 4, 2015 at 5:18 PM, Peter Geoghegan p...@heroku.com wrote:
 Attached patch series forms what I'm calling V3.0 of the INSERT ... ON
 CONFLICT IGNORE/UPDATE feature. (Sorry about all the threads. I feel
 this development justifies a new thread, though.)


Hi,

I had a play with this, mainly looking at the interaction with RLS.

(Note there is some bitrot in gram.y that prevents the first patch
from applying cleanly to HEAD)

I tested using the attached script, and one test didn't behave as I
expected. I believe the following should have been a valid upsert
(following the update path) but actually it failed:

INSERT INTO t1 VALUES (4, 0) ON CONFLICT (a) UPDATE SET b = 1;

AFAICT, it is applying a WITH CHECK OPTION with qual b  0 AND a % 2
= 0 to the about-to-be-updated tuple (a=4, b=0), which is wrong
because the b  0 check (policy p3) should only be applied to the
post-update tuple.

Possibly I'm missing something though.

Regards,
Dean
\set ECHO all
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a int PRIMARY KEY, b int);

CREATE POLICY p1 ON t1 FOR INSERT WITH CHECK (b = 0);
CREATE POLICY p2 ON t1 FOR UPDATE USING (a % 2 = 0);
CREATE POLICY p3 ON t1 FOR UPDATE WITH CHECK (b  0);

ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
SET row_security = force;

-- Valid inserts
INSERT INTO t1 VALUES (1, 0);
INSERT INTO t1 VALUES (2, 0);

-- Insert that should fail policy p1
INSERT INTO t1 VALUES (3, 1);

-- Valid update
UPDATE t1 SET b = 1 WHERE a = 2;

-- Update that should fail policy p2 (not an error, just no rows updated)
UPDATE t1 SET b = 1 WHERE a = 1;

-- Update that should fail policy p3
UPDATE t1 SET b = 0 WHERE a = 2;

-- Valid upserts (insert path)
INSERT INTO t1 VALUES (3, 0) ON CONFLICT (a) UPDATE SET b = 0;
INSERT INTO t1 VALUES (4, 0) ON CONFLICT (a) UPDATE SET b = 0;

-- Upsert (insert path) that should fail policy p1
INSERT INTO t1 VALUES (5, 1) ON CONFLICT (a) UPDATE SET b = 1;

-- Upsert (update path) that should fail policy p1
INSERT INTO t1 VALUES (3, 1) ON CONFLICT (a) UPDATE SET b = 1;

-- Valid upsert (update path)
-- XXX: Should pass, but fails WCO on t1
--  Failing WCO: (b  0 AND a % 2 = 0) = p3 AND p2
INSERT INTO t1 VALUES (4, 0) ON CONFLICT (a) UPDATE SET b = 1;

-- Upsert (update path) that should fail policy p2
INSERT INTO t1 VALUES (3, 0) ON CONFLICT (a) UPDATE SET b = 1;

-- Upsert (update path) that should fail policy p3
INSERT INTO t1 VALUES (4, 0) ON CONFLICT (a) UPDATE SET b = 0;

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

2015-03-05 Thread Peter Geoghegan
On Wed, Mar 4, 2015 at 5:18 PM, Peter Geoghegan p...@heroku.com wrote:
 Attached patch series forms what I'm calling V3.0 of the INSERT ... ON
 CONFLICT IGNORE/UPDATE feature. (Sorry about all the threads. I feel
 this development justifies a new thread, though.)

Bruce Momjian kindly made available a server for stress-testing [1].
I'm using jjanes_upsert for this task (I stopped doing this for a
little while, and was in need of a new server).

At the very highest client count I'm testing (128), I see unprincipled
deadlocks for the exclusion constraint case very infrequently:


2015-03-05 14:09:36 EST [ 64987901 ]: ERROR:  deadlock detected
2015-03-05 14:09:36 EST [ 64987901 ]: DETAIL:  Process 7044 waits for
ShareLock on promise tuple with token 1 of transaction 64987589;
blocked by process 7200.
Process 7200 waits for ShareLock on transaction 64987901;
blocked by process 7044.
Process 7044: insert into upsert_race_test (index, count)
values ('541','-1') on conflict
  update set count=TARGET.count + EXCLUDED.count
  where TARGET.index = EXCLUDED.index
  returning count
Process 7200: insert into upsert_race_test (index, count)
values ('541','-1') on conflict
  update set count=TARGET.count + EXCLUDED.count
  where TARGET.index = EXCLUDED.index
  returning count
2015-03-05 14:09:36 EST [ 64987901 ]: HINT:  See server log for query details.
2015-03-05 14:09:36 EST [ 64987901 ]: STATEMENT:  insert into
upsert_race_test (index, count) values ('541','-1') on conflict
  update set count=TARGET.count + EXCLUDED.count
  where TARGET.index = EXCLUDED.index
  returning count



(Reminder: Exclusion constraints doing UPSERTs, and not just IGNOREs,
are artificial; this has been enabled within the parser solely for the
benefit of this stress-testing. Also, the B-Tree AM does not have nor
require livelock insurance).

This only happens after just over 30 minutes, while consistently doing
128 client exclusion constraint runs. This is pretty close to the most
stressful thing that you could throw at the implementation, so that's
really not too bad.

I believe that this regression occurred as a direct result of adding
livelock insurance. Basically, we cannot be 100% sure that the
interleaving of WAL-logged things within and across transactions won't
be such that the only, oldest session that gets to wait in the
second stage (the second possible call to
check_exclusion_or_unique_constraint(), from ExecInsertIndexTuples())
will really be the oldest XID. Another *older* xact could just get
in ahead of us, waiting on our promise tuple as we wait on its xact
end (maybe it updates some third tuple that we didn't see in that has
already committed...not 100% sure). Obviously XID assignment order
does not guarantee that things like heap insertion and index tuple
insertion occur in serial XID order, especially with confounding
factors like super deletion. And so, every once in a long while we
deadlock.

Now, the very fact that this happens at all actually demonstrates the
need for livelock insurance, IMV. The fact that we reliably
terminate is *reassuring*, because livelocks are in general a
terrifying possibility. We cannot *truly* solve the unprincipled
deadlock problem without adding livelocks, I think. But what we have
here is very close to eliminating unprincipled deadlocks, while not
also adding any livelocks, AFAICT. I'd argue that that's good enough.

Of course, when I remove livelock insurance, the problem ostensibly
goes away (I've waited on such a stress test session for a couple of
hours now, so this conclusion seems very likely to be correct). I
think that we should do nothing about this, other than document it as
possible in our comments on livelock insurance. Again, it's very
unlikely to be a problem in the real world, especially since B-Trees
are unaffected.

Also, I should point out that one of those waiters doesn't look like
an insertion-related wait at all: 7200 waits for ShareLock on
transaction 64987901; blocked by process 7044. Looks like row locking
is an essential part of this deadlock, and ordinarily that isn't even
possible for exclusion constraints (unless the patch is hacked to make
the parser accept exclusion constraints for an UPSERT, as it has been
here). Not quite sure what exact  XactLockTableWait() call did this,
but don't think it was any of them within
check_exclusion_or_unique_constraint(), based on the lack of details
(TID and so on are not shown).

[1] http://momjian.us/main/blogs/pgblog/2012.html#January_20_2012
-- 
Peter Geoghegan


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers