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

Commit915de70

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 parentc2fab70 commit915de70

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
@@ -695,6 +695,7 @@ infer_arbiter_indexes(PlannerInfo *root)
695695
OnConflictExpr*onconflict=root->parse->onConflict;
696696

697697
/* Iteration state */
698+
Indexvarno;
698699
RangeTblEntry*rte;
699700
Relationrelation;
700701
OidindexOidFromConstraint=InvalidOid;
@@ -723,7 +724,8 @@ infer_arbiter_indexes(PlannerInfo *root)
723724
* the rewriter or when expand_inherited_rtentry() added it to the query's
724725
* rangetable.
725726
*/
726-
rte=rt_fetch(root->parse->resultRelation,root->parse->rtable);
727+
varno=root->parse->resultRelation;
728+
rte=rt_fetch(varno,root->parse->rtable);
727729

728730
relation=table_open(rte->relid,NoLock);
729731

@@ -857,6 +859,9 @@ infer_arbiter_indexes(PlannerInfo *root)
857859

858860
/* Expression attributes (if any) must match */
859861
idxExprs=RelationGetIndexExpressions(idxRel);
862+
if (idxExprs&&varno!=1)
863+
ChangeVarNodes((Node*)idxExprs,1,varno,0);
864+
860865
foreach(el,onconflict->arbiterElems)
861866
{
862867
InferenceElem*elem= (InferenceElem*)lfirst(el);
@@ -908,6 +913,8 @@ infer_arbiter_indexes(PlannerInfo *root)
908913
* CONFLICT's WHERE clause.
909914
*/
910915
predExprs=RelationGetIndexPredicate(idxRel);
916+
if (predExprs&&varno!=1)
917+
ChangeVarNodes((Node*)predExprs,1,varno,0);
911918

912919
if (!predicate_implied_by(predExprs, (List*)onconflict->arbiterWhere, false))
913920
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
@@ -380,6 +391,7 @@ create unique index partial_key_index on insertconflicttest(key) where fruit lik
380391
-- Succeeds
381392
insert into insertconflicttest values (23, 'Blackberry') on conflict (key) where fruit like '%berry' do update set fruit = excluded.fruit;
382393
insert into insertconflicttest as t values (23, 'Blackberry') on conflict (key) where fruit like '%berry' and t.fruit = 'inconsequential' do nothing;
394+
insert into insertconflictview as t values (23, 'Blackberry') on conflict (key) where fruit like '%berry' and t.fruit = 'inconsequential' do nothing;
383395
-- fails
384396
insert into insertconflicttest values (23, 'Blackberry') on conflict (key) do update set fruit = excluded.fruit;
385397
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
@@ -445,6 +457,7 @@ explain (costs off) insert into insertconflicttest as i values (23, 'Avocado') o
445457

446458
drop index plain;
447459
-- Cleanup
460+
drop view insertconflictview;
448461
drop table insertconflicttest;
449462
--
450463
-- 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 --
@@ -218,6 +222,7 @@ create unique index partial_key_index on insertconflicttest(key) where fruit lik
218222
-- Succeeds
219223
insert into insertconflicttestvalues (23,'Blackberry')on conflict (key)where fruitlike'%berry' doupdateset fruit=excluded.fruit;
220224
insert into insertconflicttestas tvalues (23,'Blackberry')on conflict (key)where fruitlike'%berry'andt.fruit='inconsequential' do nothing;
225+
insert into insertconflictviewas tvalues (23,'Blackberry')on conflict (key)where fruitlike'%berry'andt.fruit='inconsequential' do nothing;
221226

222227
-- fails
223228
insert into insertconflicttestvalues (23,'Blackberry')on conflict (key) doupdateset fruit=excluded.fruit;
@@ -250,6 +255,7 @@ explain (costs off) insert into insertconflicttest as i values (23, 'Avocado') o
250255
dropindex plain;
251256

252257
-- Cleanup
258+
dropview insertconflictview;
253259
droptable insertconflicttest;
254260

255261

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp