diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 8c9f8a6aeb..bd4e4956aa 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -3076,11 +3076,14 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, * (We could use this in FieldStore too, but in that case passing the old * value is so cheap there's no need.) * - * Note: it might seem that this needs to recurse, but it does not; the - * CaseTestExpr, if any, will be directly the arg or refexpr of the top-level - * node. Nested-assignment situations give rise to expression trees in which - * each level of assignment has its own CaseTestExpr, and the recursive - * structure appears within the newvals or refassgnexpr field. + * Note: it might seem that this needs to recurse, but in most cases it does + * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the + * top-level node. Nested-assignment situations give rise to expression + * trees in which each level of assignment has its own CaseTestExpr, and the + * recursive structure appears within the newvals or refassgnexpr field. + * There is an exception, though: if the array is an array-of-domain, we will + * have a CoerceToDomain as the refassgnexpr, and we need to be able to look + * through that. */ static bool isAssignmentIndirectionExpr(Expr *expr) @@ -3101,6 +3104,12 @@ isAssignmentIndirectionExpr(Expr *expr) if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr)) return true; } + else if (IsA(expr, CoerceToDomain)) + { + CoerceToDomain *cd = (CoerceToDomain *) expr; + + return isAssignmentIndirectionExpr(cd->arg); + } return false; } diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 411d5c003e..a04bd00ac6 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -512,6 +512,30 @@ LINE 1: update dposintatable set (f1[2])[1] = array[98]; drop table dposintatable; drop domain posint cascade; NOTICE: drop cascades to type dposinta +-- Test arrays over domains of composite +create type comptype as (cf1 int, cf2 int); +create domain dcomptype as comptype check ((value).cf1 > 0); +create table dcomptable (f1 dcomptype[]); +insert into dcomptable values (null); +update dcomptable set f1[1].cf2 = 5; +table dcomptable; + f1 +---------- + {"(,5)"} +(1 row) + +update dcomptable set f1[1].cf1 = -1; -- fail +ERROR: value for domain dcomptype violates check constraint "dcomptype_check" +update dcomptable set f1[1].cf1 = 1; +table dcomptable; + f1 +----------- + {"(1,5)"} +(1 row) + +drop table dcomptable; +drop type comptype cascade; +NOTICE: drop cascades to type dcomptype -- Test not-null restrictions create domain dnotnull varchar(15) NOT NULL; create domain dnull varchar(15); diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 549c0b5adf..bf48c53e9c 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -267,6 +267,23 @@ drop table dposintatable; drop domain posint cascade; +-- Test arrays over domains of composite + +create type comptype as (cf1 int, cf2 int); +create domain dcomptype as comptype check ((value).cf1 > 0); + +create table dcomptable (f1 dcomptype[]); +insert into dcomptable values (null); +update dcomptable set f1[1].cf2 = 5; +table dcomptable; +update dcomptable set f1[1].cf1 = -1; -- fail +update dcomptable set f1[1].cf1 = 1; +table dcomptable; + +drop table dcomptable; +drop type comptype cascade; + + -- Test not-null restrictions create domain dnotnull varchar(15) NOT NULL;