Skip to content

Commit 3e310d8

Browse files
committed
Fix assignment to array of domain over composite.
An update such as "UPDATE ... SET fld[n].subfld = whatever" failed if the array elements were domains rather than plain composites. That's because isAssignmentIndirectionExpr() failed to cope with the CoerceToDomain node that would appear in the expression tree in this case. The result would typically be a crash, and even if we accidentally didn't crash, we'd not correctly preserve other fields of the same array element. Per report from Onder Kalaci. Back-patch to v11 where arrays of domains came in. Discussion: https://postgr.es/m/PH0PR21MB132823A46AA36F0685B7A29AD8BD9@PH0PR21MB1328.namprd21.prod.outlook.com
1 parent 697dd19 commit 3e310d8

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

src/backend/executor/execExpr.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3092,11 +3092,14 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
30923092
* (We could use this in FieldStore too, but in that case passing the old
30933093
* value is so cheap there's no need.)
30943094
*
3095-
* Note: it might seem that this needs to recurse, but it does not; the
3096-
* CaseTestExpr, if any, will be directly the arg or refexpr of the top-level
3097-
* node. Nested-assignment situations give rise to expression trees in which
3098-
* each level of assignment has its own CaseTestExpr, and the recursive
3099-
* structure appears within the newvals or refassgnexpr field.
3095+
* Note: it might seem that this needs to recurse, but in most cases it does
3096+
* not; the CaseTestExpr, if any, will be directly the arg or refexpr of the
3097+
* top-level node. Nested-assignment situations give rise to expression
3098+
* trees in which each level of assignment has its own CaseTestExpr, and the
3099+
* recursive structure appears within the newvals or refassgnexpr field.
3100+
* There is an exception, though: if the array is an array-of-domain, we will
3101+
* have a CoerceToDomain as the refassgnexpr, and we need to be able to look
3102+
* through that.
31003103
*/
31013104
static bool
31023105
isAssignmentIndirectionExpr(Expr *expr)
@@ -3117,6 +3120,12 @@ isAssignmentIndirectionExpr(Expr *expr)
31173120
if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr))
31183121
return true;
31193122
}
3123+
else if (IsA(expr, CoerceToDomain))
3124+
{
3125+
CoerceToDomain *cd = (CoerceToDomain *) expr;
3126+
3127+
return isAssignmentIndirectionExpr(cd->arg);
3128+
}
31203129
return false;
31213130
}
31223131

src/test/regress/expected/domain.out

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,30 @@ LINE 1: update dposintatable set (f1[2])[1] = array[98];
512512
drop table dposintatable;
513513
drop domain posint cascade;
514514
NOTICE: drop cascades to type dposinta
515+
-- Test arrays over domains of composite
516+
create type comptype as (cf1 int, cf2 int);
517+
create domain dcomptype as comptype check ((value).cf1 > 0);
518+
create table dcomptable (f1 dcomptype[]);
519+
insert into dcomptable values (null);
520+
update dcomptable set f1[1].cf2 = 5;
521+
table dcomptable;
522+
f1
523+
----------
524+
{"(,5)"}
525+
(1 row)
526+
527+
update dcomptable set f1[1].cf1 = -1; -- fail
528+
ERROR: value for domain dcomptype violates check constraint "dcomptype_check"
529+
update dcomptable set f1[1].cf1 = 1;
530+
table dcomptable;
531+
f1
532+
-----------
533+
{"(1,5)"}
534+
(1 row)
535+
536+
drop table dcomptable;
537+
drop type comptype cascade;
538+
NOTICE: drop cascades to type dcomptype
515539
-- Test not-null restrictions
516540
create domain dnotnull varchar(15) NOT NULL;
517541
create domain dnull varchar(15);

src/test/regress/sql/domain.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,23 @@ drop table dposintatable;
267267
drop domain posint cascade;
268268

269269

270+
-- Test arrays over domains of composite
271+
272+
create type comptype as (cf1 int, cf2 int);
273+
create domain dcomptype as comptype check ((value).cf1 > 0);
274+
275+
create table dcomptable (f1 dcomptype[]);
276+
insert into dcomptable values (null);
277+
update dcomptable set f1[1].cf2 = 5;
278+
table dcomptable;
279+
update dcomptable set f1[1].cf1 = -1; -- fail
280+
update dcomptable set f1[1].cf1 = 1;
281+
table dcomptable;
282+
283+
drop table dcomptable;
284+
drop type comptype cascade;
285+
286+
270287
-- Test not-null restrictions
271288

272289
create domain dnotnull varchar(15) NOT NULL;

0 commit comments

Comments
 (0)