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

Commitbc2d716

Browse files
committed
Fix ruleutils.c for domain-over-array cases, too.
Further investigation shows that ruleutils isn't quite up to speed eitherfor cases where we have a domain-over-array: it needs to be prepared tolook past a CoerceToDomain at the top level of field and elementassignments, else it decompiles them incorrectly. Potentially this wouldresult in failure to dump/reload a rule, if it looked like the one in thenew test case. (I also added a test for EXPLAIN; that output isn't broken,but clearly we need more test coverage here.)Like commitb1cb32f, this bug is reachable in cases we already support,so back-patch all the way.
1 parentda11977 commitbc2d716

File tree

3 files changed

+81
-12
lines changed

3 files changed

+81
-12
lines changed

‎src/backend/utils/adt/ruleutils.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6206,8 +6206,11 @@ get_update_query_targetlist_def(Query *query, List *targetList,
62066206
/*
62076207
* We must dig down into the expr to see if it's a PARAM_MULTIEXPR
62086208
* Param. That could be buried under FieldStores and ArrayRefs
6209-
* (cf processIndirection()), and underneath those there could be
6210-
* an implicit type coercion.
6209+
* and CoerceToDomains (cf processIndirection()), and underneath
6210+
* those there could be an implicit type coercion. Because we
6211+
* would ignore implicit type coercions anyway, we don't need to
6212+
* be as careful as processIndirection() is about descending past
6213+
* implicit CoerceToDomains.
62116214
*/
62126215
expr= (Node*)tle->expr;
62136216
while (expr)
@@ -6226,6 +6229,14 @@ get_update_query_targetlist_def(Query *query, List *targetList,
62266229
break;
62276230
expr= (Node*)aref->refassgnexpr;
62286231
}
6232+
elseif (IsA(expr,CoerceToDomain))
6233+
{
6234+
CoerceToDomain*cdomain= (CoerceToDomain*)expr;
6235+
6236+
if (cdomain->coercionformat!=COERCE_IMPLICIT_CAST)
6237+
break;
6238+
expr= (Node*)cdomain->arg;
6239+
}
62296240
else
62306241
break;
62316242
}
@@ -10185,13 +10196,17 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
1018510196
*
1018610197
* We strip any top-level FieldStore or assignment ArrayRef nodes that
1018710198
* appear in the input, printing them as decoration for the base column
10188-
* name (which we assume the caller just printed). Return the subexpression
10189-
* that's to be assigned.
10199+
* name (which we assume the caller just printed). We might also need to
10200+
* strip CoerceToDomain nodes, but only ones that appear above assignment
10201+
* nodes.
10202+
*
10203+
* Returns the subexpression that's to be assigned.
1019010204
*/
1019110205
staticNode*
1019210206
processIndirection(Node*node,deparse_context*context)
1019310207
{
1019410208
StringInfobuf=context->buf;
10209+
CoerceToDomain*cdomain=NULL;
1019510210

1019610211
for (;;)
1019710212
{
@@ -10239,10 +10254,28 @@ processIndirection(Node *node, deparse_context *context)
1023910254
*/
1024010255
node= (Node*)aref->refassgnexpr;
1024110256
}
10257+
elseif (IsA(node,CoerceToDomain))
10258+
{
10259+
cdomain= (CoerceToDomain*)node;
10260+
/* If it's an explicit domain coercion, we're done */
10261+
if (cdomain->coercionformat!=COERCE_IMPLICIT_CAST)
10262+
break;
10263+
/* Tentatively descend past the CoerceToDomain */
10264+
node= (Node*)cdomain->arg;
10265+
}
1024210266
else
1024310267
break;
1024410268
}
1024510269

10270+
/*
10271+
* If we descended past a CoerceToDomain whose argument turned out not to
10272+
* be a FieldStore or array assignment, back up to the CoerceToDomain.
10273+
* (This is not enough to be fully correct if there are nested implicit
10274+
* CoerceToDomains, but such cases shouldn't ever occur.)
10275+
*/
10276+
if (cdomain&&node== (Node*)cdomain->arg)
10277+
node= (Node*)cdomain;
10278+
1024610279
returnnode;
1024710280
}
1024810281

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

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,20 +266,47 @@ insert into dcomptable (d1[1].r, d1[1].i) values(100, 99); -- fail
266266
ERROR: value for domain dcomptypea violates check constraint "c1"
267267
update dcomptable set d1[1].r = d1[1].r + 1 where d1[1].i > 0; -- fail
268268
ERROR: value for domain dcomptypea violates check constraint "c1"
269-
update dcomptable set d1[1].r = d1[1].r - 1 where d1[1].i > 0;
269+
update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1
270+
where d1[1].i > 0;
270271
select * from dcomptable;
271272
d1
272273
--------------------
273274
{"(11,)","(,)"}
274275
{"(99,)"}
275-
{"(1,2)","(,)"}
276-
{"(3,4)","(6,5)"}
277-
{"(7,8)","(10,9)"}
278-
{"(9,10)","(,)"}
279-
{"(0,2)"}
280-
{"(98,100)"}
276+
{"(1,3)","(,)"}
277+
{"(3,5)","(6,5)"}
278+
{"(7,9)","(10,9)"}
279+
{"(9,11)","(,)"}
280+
{"(0,3)"}
281+
{"(98,101)"}
281282
(8 rows)
282283

284+
explain (verbose, costs off)
285+
update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1
286+
where d1[1].i > 0;
287+
QUERY PLAN
288+
----------------------------------------------------------------------------------------------------------------
289+
Update on public.dcomptable
290+
-> Seq Scan on public.dcomptable
291+
Output: (d1[1].r := (d1[1].r - '1'::double precision))[1].i := (d1[1].i + '1'::double precision), ctid
292+
Filter: (dcomptable.d1[1].i > '0'::double precision)
293+
(4 rows)
294+
295+
create rule silly as on delete to dcomptable do instead
296+
update dcomptable set d1[1].r = d1[1].r - 1, d1[1].i = d1[1].i + 1
297+
where d1[1].i > 0;
298+
\d+ dcomptable
299+
Table "public.dcomptable"
300+
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
301+
--------+------------+-----------+----------+---------+----------+--------------+-------------
302+
d1 | dcomptypea | | | | extended | |
303+
Indexes:
304+
"dcomptable_d1_key" UNIQUE CONSTRAINT, btree (d1)
305+
Rules:
306+
silly AS
307+
ON DELETE TO dcomptable DO INSTEAD UPDATE dcomptable SET d1[1].r = dcomptable.d1[1].r - 1::double precision, d1[1].i = dcomptable.d1[1].i + 1::double precision
308+
WHERE dcomptable.d1[1].i > 0::double precision
309+
283310
drop table dcomptable;
284311
drop type comptype cascade;
285312
NOTICE: drop cascades to type dcomptypea

‎src/test/regress/sql/domain.sql

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,18 @@ insert into dcomptable (d1[1].r) values(99);
150150
insert into dcomptable (d1[1].r, d1[1].i)values(99,100);
151151
insert into dcomptable (d1[1].r, d1[1].i)values(100,99);-- fail
152152
update dcomptableset d1[1].r= d1[1].r+1where d1[1].i>0;-- fail
153-
update dcomptableset d1[1].r= d1[1].r-1where d1[1].i>0;
153+
update dcomptableset d1[1].r= d1[1].r-1, d1[1].i= d1[1].i+1
154+
where d1[1].i>0;
154155
select*from dcomptable;
155156

157+
explain (verbose, costs off)
158+
update dcomptableset d1[1].r= d1[1].r-1, d1[1].i= d1[1].i+1
159+
where d1[1].i>0;
160+
createrulesillyason delete to dcomptable do instead
161+
update dcomptableset d1[1].r= d1[1].r-1, d1[1].i= d1[1].i+1
162+
where d1[1].i>0;
163+
\d+ dcomptable
164+
156165
droptable dcomptable;
157166
droptype comptype cascade;
158167

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp