Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5e8aa32

Browse files
committed
Fix infer_arbiter_indexes() to not assume resultRelation is 1.
infer_arbiter_indexes failed to renumber varnos in index expressionsor predicates that it got from the catalogs. This escaped detectionup to now because the stored varnos in such trees will be 1, and anINSERT's result relation is usually the first rangetable entry,so that that was fine. However, in cases such as inserting throughan updatable view, it's not fine, leading to failure to match theexpressions to the query with ensuing "there is no unique or exclusionconstraint matching the ON CONFLICT specification" errors.Fix by copy-and-paste from get_relation_info().Per bug #18502 from Michael Wang. Back-patch to all supportedversions.Discussion:https://postgr.es/m/18502-545b53f5b81e54e0@postgresql.org
1 parentd8062ea commit5e8aa32

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

‎src/backend/optimizer/util/plancat.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ infer_arbiter_indexes(PlannerInfo *root)
622622
OnConflictExpr*onconflict=root->parse->onConflict;
623623

624624
/* Iteration state */
625+
Indexvarno;
625626
RangeTblEntry*rte;
626627
Relationrelation;
627628
OidindexOidFromConstraint=InvalidOid;
@@ -650,7 +651,8 @@ infer_arbiter_indexes(PlannerInfo *root)
650651
* the rewriter or when expand_inherited_rtentry() added it to the query's
651652
* rangetable.
652653
*/
653-
rte=rt_fetch(root->parse->resultRelation,root->parse->rtable);
654+
varno=root->parse->resultRelation;
655+
rte=rt_fetch(varno,root->parse->rtable);
654656

655657
relation=table_open(rte->relid,NoLock);
656658

@@ -784,6 +786,9 @@ infer_arbiter_indexes(PlannerInfo *root)
784786

785787
/* Expression attributes (if any) must match */
786788
idxExprs=RelationGetIndexExpressions(idxRel);
789+
if (idxExprs&&varno!=1)
790+
ChangeVarNodes((Node*)idxExprs,1,varno,0);
791+
787792
foreach(el,onconflict->arbiterElems)
788793
{
789794
InferenceElem*elem= (InferenceElem*)lfirst(el);
@@ -835,6 +840,8 @@ infer_arbiter_indexes(PlannerInfo *root)
835840
* CONFLICT's WHERE clause.
836841
*/
837842
predExprs=RelationGetIndexPredicate(idxRel);
843+
if (predExprs&&varno!=1)
844+
ChangeVarNodes((Node*)predExprs,1,varno,0);
838845

839846
if (!predicate_implied_by(predExprs, (List*)onconflict->arbiterWhere, false))
840847
gotonext;

‎src/test/regress/expected/insert_conflict.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
-- insert...on conflict do unique index inference
33
--
44
create table insertconflicttest(key int4, fruit text);
5+
-- These things should work through a view, as well
6+
create view insertconflictview as select * from insertconflicttest;
57
--
68
-- Test unique index inference with operator class specifications and
79
-- named collations
@@ -43,6 +45,15 @@ explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on con
4345
-> Result
4446
(4 rows)
4547

48+
explain (costs off) insert into insertconflictview values(0, 'Crowberry') on conflict (lower(fruit), key, lower(fruit), key) do nothing;
49+
QUERY PLAN
50+
-------------------------------------------------
51+
Insert on insertconflicttest
52+
Conflict Resolution: NOTHING
53+
Conflict Arbiter Indexes: both_index_expr_key
54+
-> Result
55+
(4 rows)
56+
4657
explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on conflict (key, fruit) do update set fruit = excluded.fruit
4758
where exists (select 1 from insertconflicttest ii where ii.key = excluded.key);
4859
QUERY PLAN
@@ -374,6 +385,7 @@ create unique index partial_key_index on insertconflicttest(key) where fruit lik
374385
-- Succeeds
375386
insert into insertconflicttest values (23, 'Blackberry') on conflict (key) where fruit like '%berry' do update set fruit = excluded.fruit;
376387
insert into insertconflicttest values (23, 'Blackberry') on conflict (key) where fruit like '%berry' and fruit = 'inconsequential' do nothing;
388+
insert into insertconflictview values (23, 'Blackberry') on conflict (key) where fruit like '%berry' and fruit = 'inconsequential' do nothing;
377389
-- fails
378390
insert into insertconflicttest values (23, 'Blackberry') on conflict (key) do update set fruit = excluded.fruit;
379391
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
@@ -439,6 +451,7 @@ explain (costs off) insert into insertconflicttest as i values (23, 'Avocado') o
439451

440452
drop index plain;
441453
-- Cleanup
454+
drop view insertconflictview;
442455
drop table insertconflicttest;
443456
--
444457
-- Verify that EXCLUDED does not allow system column references. These

‎src/test/regress/sql/insert_conflict.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
--
44
createtableinsertconflicttest(key int4, fruittext);
55

6+
-- These things should work through a view, as well
7+
createviewinsertconflictviewasselect*from insertconflicttest;
8+
69
--
710
-- Test unique index inference with operator class specifications and
811
-- named collations
@@ -20,6 +23,7 @@ explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on con
2023
explain (costs off)insert into insertconflicttestvalues(0,'Crowberry')on conflict (key, fruit) do nothing;
2124
explain (costs off)insert into insertconflicttestvalues(0,'Crowberry')on conflict (fruit, key, fruit, key) do nothing;
2225
explain (costs off)insert into insertconflicttestvalues(0,'Crowberry')on conflict (lower(fruit), key,lower(fruit), key) do nothing;
26+
explain (costs off)insert into insertconflictviewvalues(0,'Crowberry')on conflict (lower(fruit), key,lower(fruit), key) do nothing;
2327
explain (costs off)insert into insertconflicttestvalues(0,'Crowberry')on conflict (key, fruit) doupdateset fruit=excluded.fruit
2428
where exists (select1from insertconflicttest iiwhereii.key=excluded.key);
2529
-- Neither collation nor operator class specifications are required --
@@ -215,6 +219,7 @@ create unique index partial_key_index on insertconflicttest(key) where fruit lik
215219
-- Succeeds
216220
insert into insertconflicttestvalues (23,'Blackberry')on conflict (key)where fruitlike'%berry' doupdateset fruit=excluded.fruit;
217221
insert into insertconflicttestvalues (23,'Blackberry')on conflict (key)where fruitlike'%berry'and fruit='inconsequential' do nothing;
222+
insert into insertconflictviewvalues (23,'Blackberry')on conflict (key)where fruitlike'%berry'and fruit='inconsequential' do nothing;
218223

219224
-- fails
220225
insert into insertconflicttestvalues (23,'Blackberry')on conflict (key) doupdateset fruit=excluded.fruit;
@@ -247,6 +252,7 @@ explain (costs off) insert into insertconflicttest as i values (23, 'Avocado') o
247252
dropindex plain;
248253

249254
-- Cleanup
255+
dropview insertconflictview;
250256
droptable insertconflicttest;
251257

252258

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp