Thread: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
[BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
tiago.babo@gmail.com
Date:
The following bug has been logged on the website: Bug reference: 14526 Logged by: Tiago Babo Email address: tiago.babo@gmail.com PostgreSQL version: 9.5.5 Operating system: Ubuntu 14.04.2 LTS Description: I'm getting the following error when doing the following type of insert: Errpr: SQL execution failed (Reason: ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification) Query: INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 1) ON CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET updated_at = EXCLUDED.updated_at RETURNING * I also have an unique INDEX: CREATE UNIQUE INDEX uniq_person_accounts ON accounts USING btree (type, person_id) WHERE ((type)::text = 'PersonAccount'::text); The thing is that sometimes it works, but not every time. I "randomly" get that exception, which is really strange. It seems that it can't access that INDEX or it doesn't know it exists. Any suggestion? -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Thu, Feb 2, 2017 at 6:07 AM, <tiago.babo@gmail.com> wrote: > INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 1) ON > CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET > updated_at = EXCLUDED.updated_at RETURNING * > > I also have an unique INDEX: > > CREATE UNIQUE INDEX uniq_person_accounts ON accounts USING btree (type, > person_id) WHERE ((type)::text = 'PersonAccount'::text); Can you show the table definition? From psql, "\d+ accounts" -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Tiago Babo
Date:
Here it goes: Table "public.accounts" Column | Type | Modifiers |Storage | Stats target | Description ----------------------------------+-----------------------------+-------------------------------------------------------+----------+--------------+------------- id | integer | not null default nextval('accounts_id_seq'::regclass) |plain | | type | character varying | |extended | | identifier | character varying | |extended | | person_id | integer | |plain | | business_id | integer | |plain | | Indexes: "accounts_pkey" PRIMARY KEY, btree (id) "index_accounts_on_type_and_identifier" UNIQUE, btree (type, identifier) "uniq_bank_accounts" UNIQUE, btree (type, identifier) WHERE type::text = 'BankAccount'::text "uniq_business_accounts" UNIQUE, btree (type, business_id) WHERE type::text = 'BusinessAccount'::text "uniq_person_accounts" UNIQUE, btree (person_id) WHERE type::text = 'PersonAccount'::text "index_accounts_on_business_id" btree (business_id) "index_accounts_on_person_id" btree (person_id) Foreign-key constraints: "fk_rails_156241f05a" FOREIGN KEY (business_id) REFERENCES businesses(id) "fk_rails_777d10a224" FOREIGN KEY (person_id) REFERENCES persons(id) > On 7 Feb 2017, at 09:03, Peter Geoghegan <pg@bowt.ie> wrote: > > On Thu, Feb 2, 2017 at 6:07 AM, <tiago.babo@gmail.com> wrote: >> INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 1) ON >> CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET >> updated_at = EXCLUDED.updated_at RETURNING * >> >> I also have an unique INDEX: >> >> CREATE UNIQUE INDEX uniq_person_accounts ON accounts USING btree (type, >> person_id) WHERE ((type)::text = 'PersonAccount'::text); > > Can you show the table definition? From psql, "\d+ accounts" > > > -- > Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Tiago Babo <tiago.babo@gmail.com> writes: > Indexes: > "accounts_pkey" PRIMARY KEY, btree (id) > "index_accounts_on_type_and_identifier" UNIQUE, btree (type, identifier) > "uniq_bank_accounts" UNIQUE, btree (type, identifier) WHERE type::text = 'BankAccount'::text > "uniq_business_accounts" UNIQUE, btree (type, business_id) WHERE type::text = 'BusinessAccount'::text > "uniq_person_accounts" UNIQUE, btree (person_id) WHERE type::text = 'PersonAccount'::text > "index_accounts_on_business_id" btree (business_id) > "index_accounts_on_person_id" btree (person_id) So according to that, you *don't* have a unique index over (type, person_id). (A sufficiently clever person might realize that the partial index on person_id would serve in this instance, but I do not expect that Postgres would figure that out.) That makes the question less about why it fails and more about why it seems to sometimes work. It shouldn't, at least not with this set of indexes and this query. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Tiago Babo
Date:
Ups, I used the wrong database. I was experimenting with it a bit and didn’t noticed I was copying from the wrong one. Whereis the correct version (and the one that is giving me those “random” errors): Column | Type | Modifiers |Storage | Stats target | Description ----------------------------------+-----------------------------+-------------------------------------------------------+----------+--------------+------------- id | integer | not null default nextval('accounts_id_seq'::regclass) |plain | | type | character varying | |extended | | identifier | character varying | |extended | | person_id | integer | |plain | | business_id | integer | |plain | | Indexes: "accounts_pkey" PRIMARY KEY, btree (id) "index_accounts_on_type_and_identifier" UNIQUE, btree (type, identifier) "uniq_bank_accounts" UNIQUE, btree (type, identifier) WHERE type::text = 'BankAccount'::text "uniq_business_accounts" UNIQUE, btree (type, business_id) WHERE type::text = 'BusinessAccount'::text "uniq_person_accounts" UNIQUE, btree (type, person_id) WHERE type::text = 'PersonAccount'::text "index_accounts_on_business_id" btree (business_id) "index_accounts_on_person_id" btree (person_id) Foreign-key constraints: "fk_rails_156241f05a" FOREIGN KEY (business_id) REFERENCES businesses(id) "fk_rails_777d10a224" FOREIGN KEY (person_id) REFERENCES persons(id) > On 7 Feb 2017, at 18:54, Tom Lane <tgl@sss.pgh.pa.us> wrote: > > Tiago Babo <tiago.babo@gmail.com> writes: >> Indexes: >> "accounts_pkey" PRIMARY KEY, btree (id) >> "index_accounts_on_type_and_identifier" UNIQUE, btree (type, identifier) >> "uniq_bank_accounts" UNIQUE, btree (type, identifier) WHERE type::text = 'BankAccount'::text >> "uniq_business_accounts" UNIQUE, btree (type, business_id) WHERE type::text = 'BusinessAccount'::text >> "uniq_person_accounts" UNIQUE, btree (person_id) WHERE type::text = 'PersonAccount'::text >> "index_accounts_on_business_id" btree (business_id) >> "index_accounts_on_person_id" btree (person_id) > > So according to that, you *don't* have a unique index over (type, person_id). > (A sufficiently clever person might realize that the partial index on > person_id would serve in this instance, but I do not expect that Postgres > would figure that out.) > > That makes the question less about why it fails and more about why it > seems to sometimes work. It shouldn't, at least not with this set of > indexes and this query. > > regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 10:54 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > That makes the question less about why it fails and more about why it > seems to sometimes work. It shouldn't, at least not with this set of > indexes and this query. Agreed. Log output from Tiago's system, with debug_print_parse = on, debug_print_plan = on, and debug_print_rewritten = on might tell us some more. If Tiago can enable those at a time that catches the successful execution of the query (where inference mysteriously works), we'd have a good chance of understanding what's up. (This is probably something to be done quite selectively in production.) -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Tiago Babo <tiago.babo@gmail.com> writes: > Ups, I used the wrong database. I was experimenting with it a bit and didn’t noticed I was copying from the wrong one.Where is the correct version (and the one that is giving me those “random” errors): > Indexes: > "accounts_pkey" PRIMARY KEY, btree (id) > "index_accounts_on_type_and_identifier" UNIQUE, btree (type, identifier) > "uniq_bank_accounts" UNIQUE, btree (type, identifier) WHERE type::text = 'BankAccount'::text > "uniq_business_accounts" UNIQUE, btree (type, business_id) WHERE type::text = 'BusinessAccount'::text > "uniq_person_accounts" UNIQUE, btree (type, person_id) WHERE type::text = 'PersonAccount'::text > "index_accounts_on_business_id" btree (business_id) > "index_accounts_on_person_id" btree (person_id) Hm. I looked at infer_arbiter_indexes, which is the place where this particular error is thrown, and realized that my previous assertion was wrong: it *does* try to prove applicability of partial indexes based on the ON CONFLICT WHERE clause. So actually it should be deciding that uniq_person_accounts is a usable unique index --- at least, if you always have "WHERE type = 'PersonAccount'" in the ON CONFLICT clause. Maybe you're sometimes leaving that out? (BTW, I would say that uniq_bank_accounts is absolutely not worth its keep given that you have a non-partial unique index on the same two columns. But that seems not very relevant to the current complaint.) regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 12:44 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Hm. I looked at infer_arbiter_indexes, which is the place where this > particular error is thrown, and realized that my previous assertion > was wrong: it *does* try to prove applicability of partial indexes > based on the ON CONFLICT WHERE clause. I must have misunderstood. ON CONFLICT accepts a WHERE clause as part of the inference specification itself entirely because that is sometimes useful. > So actually it should be > deciding that uniq_person_accounts is a usable unique index --- at > least, if you always have "WHERE type = 'PersonAccount'" in the > ON CONFLICT clause. Maybe you're sometimes leaving that out? That's the simplest answer. Tiago? -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Tiago Babo
Date:
Thanks for your replies.
Peter Geoghegan <pg@bowt.ie> escreveu no dia terça, 7/02/2017 às 21:27:
On Tue, Feb 7, 2017 at 12:44 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Hm. I looked at infer_arbiter_indexes, which is the place where this
> particular error is thrown, and realized that my previous assertion
> was wrong: it *does* try to prove applicability of partial indexes
> based on the ON CONFLICT WHERE clause.
I must have misunderstood. ON CONFLICT accepts a WHERE clause as part
of the inference specification itself entirely because that is
sometimes useful.
> So actually it should be
> deciding that uniq_person_accounts is a usable unique index --- at
> least, if you always have "WHERE type = 'PersonAccount'" in the
> ON CONFLICT clause. Maybe you're sometimes leaving that out?
That's the simplest answer. Tiago?
There is only one place where I create accounts, so the query is always the same.
Here is an example where it gives the error (I excluded the created_at and updated_at columns in the last e-mail, but they do exist in the table):
INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 69559, '2017-02-03 12:09:27.259', '2017-02-03 12:09:27.259') ON CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET updated_at = EXCLUDED.updated_at RETURNING *
SQL execution failed (Reason: ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification)
--
Peter Geoghegan
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 2:15 PM, Tiago Babo <tiago.babo@gmail.com> wrote: > Here is an example where it gives the error (I excluded the created_at and > updated_at columns in the last e-mail, but they do exist in the table): > > INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 69559, > '2017-02-03 12:09:27.259', '2017-02-03 12:09:27.259') ON CONFLICT (type, > person_id) WHERE type = 'PersonAccount' DO UPDATE SET updated_at = > EXCLUDED.updated_at RETURNING * Can you give an example of where it does actually work? Is there any discernible pattern to what each case looks like? -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Tiago Babo
Date:
The only difference (so it seems), is that when it crashes, the person was created in the seconds before creating the account.When it previously exists in the persons table, it never gives the error. Working example: INSERT INTO accounts (type, person_id, created_at, updated_at) VALUES (‘PersonAccount', 137842, '2017-02-07 23:17:37.61', '2017-02-07 23:17:37.61') ON CONFLICT (type, person_id) WHERE type = ‘PersonAccount' DO UPDATE SET updated_at = EXCLUDED.updated_at RETURNING * > On 7 Feb 2017, at 22:17, Peter Geoghegan <pg@bowt.ie> wrote: > > On Tue, Feb 7, 2017 at 2:15 PM, Tiago Babo <tiago.babo@gmail.com> wrote: >> Here is an example where it gives the error (I excluded the created_at and >> updated_at columns in the last e-mail, but they do exist in the table): >> >> INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 69559, >> '2017-02-03 12:09:27.259', '2017-02-03 12:09:27.259') ON CONFLICT (type, >> person_id) WHERE type = 'PersonAccount' DO UPDATE SET updated_at = >> EXCLUDED.updated_at RETURNING * > > Can you give an example of where it does actually work? Is there any > discernible pattern to what each case looks like? > > > -- > Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 3:21 PM, Tiago Babo <tiago.babo@gmail.com> wrote: > The only difference (so it seems), is that when it crashes, the person was created in the seconds before creating the account.When it previously exists in the persons table, it never gives the error. It crashes? Anyway, it's very hard to see how that could be, since the error in question is thrown from within the planner. I don't recall the exact details of how inference will do offhand, but I am suspicious of the cast that appears in the partial index predicate. -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Tiago Babo
Date:
Maybe it was not the best use of the word "crashes". It gives me the error I showed you.
I don't really understand how PostgreSQL handles indexes, but would it be possible that the INDEX is being used/updated at that moment and so the INSERT doesn't know it exists? Can concurrency also be a problem?
Peter Geoghegan <pg@bowt.ie> escreveu no dia terça, 7/02/2017 às 23:36:
On Tue, Feb 7, 2017 at 3:21 PM, Tiago Babo <tiago.babo@gmail.com> wrote:
> The only difference (so it seems), is that when it crashes, the person was created in the seconds before creating the account. When it previously exists in the persons table, it never gives the error.
It crashes?
Anyway, it's very hard to see how that could be, since the error in
question is thrown from within the planner. I don't recall the exact
details of how inference will do offhand, but I am suspicious of the
cast that appears in the partial index predicate.
--
Peter Geoghegan
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Peter Geoghegan <pg@bowt.ie> writes: > Anyway, it's very hard to see how that could be, since the error in > question is thrown from within the planner. Yeah, there really shouldn't be any data dependency there. > I don't recall the exact > details of how inference will do offhand, but I am suspicious of the > cast that appears in the partial index predicate. That's expected given that the column is declared varchar. The whole thing is pretty strange. I could believe the test not finding an index whose state is changing (ie, it's in process of being built by CREATE INDEX CONCURRENTLY), but as long as the pg_index entry is stable it seems like it should either work or not. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 3:46 PM, Tiago Babo <tiago.babo@gmail.com> wrote: > I don't really understand how PostgreSQL handles indexes, but would it be > possible that the INDEX is being used/updated at that moment and so the > INSERT doesn't know it exists? Can concurrency also be a problem? Anything is possible, I suppose, but that seems very unlikely to be a factor here. Any problem like this occurs in codepaths that only consider metadata -- the definition of indexes themselves, underlying types, and so on. This presumably never changes here; you aren't creating and dropping indexes on the table in question around the time you see problems. -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
btw ... not relevant to this particular complaint, but I notice that infer_arbiter_indexes will accept an index that is indisvalid and indisunique, but should it be checking indimmediate as well? That is, does the ON CONFLICT code work if the uniqueness checks are deferred? I could not find any regression tests exercising such a case. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Tiago Babo <tiago.babo@gmail.com> writes: > I don't really understand how PostgreSQL handles indexes, but would it be > possible that the INDEX is being used/updated at that moment and so the > INSERT doesn't know it exists? Can concurrency also be a problem? Data activity shouldn't matter. If you're dropping and recreating the whole index, that could matter. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tiago Babo
Date:
No, I'm not doing that. The index was just created once. > On 8 Feb 2017, at 00:04, Tom Lane <tgl@sss.pgh.pa.us> wrote: > > Tiago Babo <tiago.babo@gmail.com> writes: >> I don't really understand how PostgreSQL handles indexes, but would it be >> possible that the INDEX is being used/updated at that moment and so the >> INSERT doesn't know it exists? Can concurrency also be a problem? > > Data activity shouldn't matter. If you're dropping and recreating the > whole index, that could matter. > > regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Tiago Babo <tiago.babo@gmail.com> writes: > No, I'm not doing that. The index was just created once. Whole thing is as weird as can be. Maybe you could work on creating a reproducible test case? regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 3:57 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > btw ... not relevant to this particular complaint, but I notice that > infer_arbiter_indexes will accept an index that is indisvalid and > indisunique, but should it be checking indimmediate as well? That is, > does the ON CONFLICT code work if the uniqueness checks are deferred? > I could not find any regression tests exercising such a case. It won't work with deferrable constraints (even when immediate enforcement is in effect, so obscure reasons). Enforcement occurs in the executor -- see ExecCheckIndexConstraints(). You may recall that I wrote a refactoring patch that attempted to make the situation clearer, which Heikki didn't like. Currently, the constant UNIQUE_CHECK_PARTIAL is sort of overloaded to also be used with speculative insertion, which, aside from being ugly, has various minor practical disadvantages. -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Tue, Feb 7, 2017 at 5:41 PM, Peter Geoghegan <pg@bowt.ie> wrote: > It won't work with deferrable constraints (even when immediate > enforcement is in effect, so obscure reasons). Enforcement occurs in > the executor -- see ExecCheckIndexConstraints(). Note also that it needs to happen in the executor, because infer_arbiter_indexes() may return immediately when ON CONFLICT DO NOTHING is used without the user specifying which particular constraint to use as an arbiter. (This is forbidden with ON CONFLICT DO UPDATE, since it doesn't make sense to not have an arbiter in mind there.) This is actually noted directly within infer_arbiter_indexes(), about half way down: /* * Extract info from the relation descriptor for the index. We know * that this is a target, so get lock type it is known will ultimately * be required by the executor. * * Let executor complain about !indimmediate case directly, because * enforcement needs to occur there anyway when an inference clause is * omitted. */ -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Tiago Babo
Date:
Hi, again. After some testing, I was able to reproduce this error with the following code: CREATE TABLE test ( type character varying, id integer ); CREATE UNIQUE INDEX uniq_id_test ON test USING btree (type, id) WHERE (type = 'Test'); PREPARE test (text, int, text) AS INSERT INTO test (type, id) VALUES ($1, $2) ON CONFLICT (type, id) WHERE type = $3 DO UPDATE SET id = EXCLUDED.id; EXECUTE test('Test', 1, 'Test'); EXECUTE test('Test', 2, 'Test'); EXECUTE test('Test', 3, 'Test'); EXECUTE test('Test', 4, 'Test'); EXECUTE test('Test', 5, 'Test'); EXECUTE test('Test', 6, 'Test’); It gives the error when trying to execute the last statement. > On 8 Feb 2017, at 01:48, Peter Geoghegan <pg@bowt.ie> wrote: > > On Tue, Feb 7, 2017 at 5:41 PM, Peter Geoghegan <pg@bowt.ie> wrote: >> It won't work with deferrable constraints (even when immediate >> enforcement is in effect, so obscure reasons). Enforcement occurs in >> the executor -- see ExecCheckIndexConstraints(). > > Note also that it needs to happen in the executor, because > infer_arbiter_indexes() may return immediately when ON CONFLICT DO > NOTHING is used without the user specifying which particular > constraint to use as an arbiter. (This is forbidden with ON CONFLICT > DO UPDATE, since it doesn't make sense to not have an arbiter in mind > there.) > > This is actually noted directly within infer_arbiter_indexes(), about > half way down: > > /* > * Extract info from the relation descriptor for the index. We know > * that this is a target, so get lock type it is known will ultimately > * be required by the executor. > * > * Let executor complain about !indimmediate case directly, because > * enforcement needs to occur there anyway when an inference clause is > * omitted. > */ > > -- > Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Tiago Babo <tiago.babo@gmail.com> writes: > Hi, again. After some testing, I was able to reproduce this error with the following code: > CREATE UNIQUE INDEX uniq_id_test ON test USING btree (type, id) WHERE (type = 'Test'); > PREPARE test (text, int, text) AS > INSERT INTO test (type, id) > VALUES ($1, $2) > ON CONFLICT (type, id) WHERE type = $3 DO UPDATE SET id = EXCLUDED.id; > EXECUTE test('Test', 1, 'Test'); > EXECUTE test('Test', 2, 'Test'); > EXECUTE test('Test', 3, 'Test'); > EXECUTE test('Test', 4, 'Test'); > EXECUTE test('Test', 5, 'Test'); > EXECUTE test('Test', 6, 'Test'); > It gives the error when trying to execute the last statement. Hm. So the problem here is that the prepared statement only matches the partial index as long as the actual parameter is substituted literally into the statement. As soon as the plancache tries to consider a generic plan, in which it's not apparent at plan time what $3 is, we can't prove the partial index to be matched so you get the error. If this is representative of what your application is actually doing, rather than what you were saying it does, then the answer is that you have to match the partial index clause exactly, not rely on substitution/ simplification to produce a match. Or don't use a partial index. That schema seems pretty bizarre to me anyway. Having said all that, I think this is a fine example of why relying on planner inferences for semantic decisions (rather than just optimization) is damn-fool design. If I'd been paying closer attention I would have objected loudly to the use of WHERE in ON CONFLICT for this purpose. I wonder whether it's too late to deprecate that feature. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tiago Babo
Date:
This is not how my application is doing the insert (like I showed you before), but it was the only way I could continuouslyget the error. I'm using a Scala library called ScalikeJDBC to access the database. So maybe the problem is onhow it handles the execution. > On 8 Feb 2017, at 17:09, Tom Lane <tgl@sss.pgh.pa.us> wrote: > > Tiago Babo <tiago.babo@gmail.com> writes: >> Hi, again. After some testing, I was able to reproduce this error with the following code: > >> CREATE UNIQUE INDEX uniq_id_test ON test USING btree (type, id) WHERE (type = 'Test'); > >> PREPARE test (text, int, text) AS >> INSERT INTO test (type, id) >> VALUES ($1, $2) >> ON CONFLICT (type, id) WHERE type = $3 DO UPDATE SET id = EXCLUDED.id; > >> EXECUTE test('Test', 1, 'Test'); >> EXECUTE test('Test', 2, 'Test'); >> EXECUTE test('Test', 3, 'Test'); >> EXECUTE test('Test', 4, 'Test'); >> EXECUTE test('Test', 5, 'Test'); >> EXECUTE test('Test', 6, 'Test'); > >> It gives the error when trying to execute the last statement. > > Hm. So the problem here is that the prepared statement only matches the > partial index as long as the actual parameter is substituted literally > into the statement. As soon as the plancache tries to consider a generic > plan, in which it's not apparent at plan time what $3 is, we can't prove > the partial index to be matched so you get the error. > > If this is representative of what your application is actually doing, > rather than what you were saying it does, then the answer is that you > have to match the partial index clause exactly, not rely on substitution/ > simplification to produce a match. > > Or don't use a partial index. That schema seems pretty bizarre to me > anyway. > > Having said all that, I think this is a fine example of why relying on > planner inferences for semantic decisions (rather than just optimization) > is damn-fool design. If I'd been paying closer attention I would have > objected loudly to the use of WHERE in ON CONFLICT for this purpose. > I wonder whether it's too late to deprecate that feature. > > regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Tiago Babo <tiago.babo@gmail.com> writes: > This is not how my application is doing the insert (like I showed you before), but it was the only way I could continuouslyget the error. I'm using a Scala library called ScalikeJDBC to access the database. So maybe the problem is onhow it handles the execution. You should turn on log_statements and look to see what's actually being sent to the server. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Wed, Feb 8, 2017 at 9:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Having said all that, I think this is a fine example of why relying on > planner inferences for semantic decisions (rather than just optimization) > is damn-fool design. If I'd been paying closer attention I would have > objected loudly to the use of WHERE in ON CONFLICT for this purpose. > I wonder whether it's too late to deprecate that feature. I never imagined that somebody would want to parameterize constants in the WHERE clause, because that's contrary to the idea that the semantics are expressed explicitly from SQL. There may have been a failure of imagination on my part about how that interacts with certain driver libraries, but that doesn't invalidate the idea of inference of partial indexes. I do think that it's very valuable that inference supports partial indexes. Back when I was an application developer, I extensively used partial unique indexes to support "logical deletion" of records. There were many unique indexes "WHERE NOT is_deleted" or similar. *Most* unique constraints ended up being implemented this way. Since partial indexes are necessarily never constraints as such, users cannot spell out their name directly, and so inference of some form must be used. ON CONFLICT would be totally closed off to an app that did that were it not for inference of partial indexes, so it does seem very important to me. If you want to talk about making this less surprising, I think that that would definitely need to be more nuanced than simply not accepting a WHERE clause in the inference specification. I would strongly object to that. -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
Peter Geoghegan <pg@bowt.ie> writes: > On Tue, Feb 7, 2017 at 5:41 PM, Peter Geoghegan <pg@bowt.ie> wrote: >> It won't work with deferrable constraints (even when immediate >> enforcement is in effect, so obscure reasons). Enforcement occurs in >> the executor -- see ExecCheckIndexConstraints(). > This is actually noted directly within infer_arbiter_indexes(), about > half way down: > * Let executor complain about !indimmediate case directly, because > * enforcement needs to occur there anyway when an inference clause is > * omitted. I'm not following. If the executor needs to check too, that's fine, but why is it okay for the planner not to check? Assume that for some weird reason the user has both indimmediate and !indimmediate indexes on the same column set. If the planner chooses the wrong one, don't bad things happen? If it doesn't matter which index the planner picks, why are we doing this at plan time at all? regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching theON CONFLICT
From
Peter Geoghegan
Date:
On Wed, Feb 8, 2017 at 10:51 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > I'm not following. If the executor needs to check too, that's fine, > but why is it okay for the planner not to check? Assume that for some > weird reason the user has both indimmediate and !indimmediate indexes > on the same column set. If the planner chooses the wrong one, don't > bad things happen? No, because the planner isn't limited to picking just one. It is generally very likely that only one will be chosen, but edge cases like this are considered. infer_arbiter_indexes() returns a list of Oids of indexes. -- Peter Geoghegan -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matchingthe ON CONFLICT
From
David Gould
Date:
On Wed, 08 Feb 2017 12:31:58 -0500 Tom Lane <tgl@sss.pgh.pa.us> wrote: > Tiago Babo <tiago.babo@gmail.com> writes: > > This is not how my application is doing the insert (like I showed you before), but it was the only way I could continuouslyget the error. I'm using a Scala library called ScalikeJDBC to access the database. So maybe the problem is onhow it handles the execution. > > You should turn on log_statements and look to see what's actually being > sent to the server. Last time I looked, the JDBC driver always uses prepared statements. -dg -- David Gould 510 282 0869 daveg@sonic.net If simplicity worked, the world would be overrun with insects. -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tom Lane
Date:
David Gould <daveg@sonic.net> writes: > Tom Lane <tgl@sss.pgh.pa.us> wrote: >> You should turn on log_statements and look to see what's actually being >> sent to the server. > Last time I looked, the JDBC driver always uses prepared statements. Yeah, but does JDBC actually pull literal constants out of the query string and send them as separate parameter values? That seems like a pretty dumb idea. regards, tom lane -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matchingthe ON CONFLICT
From
David Gould
Date:
On Wed, 08 Feb 2017 18:57:16 -0500 Tom Lane <tgl@sss.pgh.pa.us> wrote: > David Gould <daveg@sonic.net> writes: > > Tom Lane <tgl@sss.pgh.pa.us> wrote: > >> You should turn on log_statements and look to see what's actually being > >> sent to the server. > > > Last time I looked, the JDBC driver always uses prepared statements. > > Yeah, but does JDBC actually pull literal constants out of the query > string and send them as separate parameter values? That seems like a > pretty dumb idea. I'm guessing that the actual call from Scala uses parameters for this part instead of duplicating the same query with only the qualification changing. Tiago, can you show us the actual code that runs this statement? -dg -- David Gould 510 282 0869 daveg@sonic.net If simplicity worked, the world would be overrun with insects. -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs
Re: [BUGS] BUG #14526: no unique or exclusion constraint matching the ON CONFLICT
From
Tiago Babo
Date:
Yes, you're right. I'm using parameters for that part of the query. > On 9 Feb 2017, at 02:00, David Gould <daveg@sonic.net> wrote: > > On Wed, 08 Feb 2017 18:57:16 -0500 > Tom Lane <tgl@sss.pgh.pa.us> wrote: > >> David Gould <daveg@sonic.net> writes: >>> Tom Lane <tgl@sss.pgh.pa.us> wrote: >>>> You should turn on log_statements and look to see what's actually being >>>> sent to the server. >> >>> Last time I looked, the JDBC driver always uses prepared statements. >> >> Yeah, but does JDBC actually pull literal constants out of the query >> string and send them as separate parameter values? That seems like a >> pretty dumb idea. > > I'm guessing that the actual call from Scala uses parameters for this > part instead of duplicating the same query with only the qualification > changing. > > Tiago, can you show us the actual code that runs this statement? > > -dg > > -- > David Gould 510 282 0869 daveg@sonic.net > If simplicity worked, the world would be overrun with insects. -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs