=== Applying patches on top of PostgreSQL commit ID a2b02293bc65dbb2401cb19c724f52c6ee0f2faf === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Thu Nov 6 20:45:23 UTC 2025 On branch cf/5725 nothing to commit, working tree clean === using 'git am' to apply patch ./v2-0001-rename-ExecComputeStoredGenerated-to-ExecComputeGenerated.patch === Applying: rename ExecComputeStoredGenerated to ExecComputeGenerated === using 'git am' to apply patch ./v2-0002-soft-error-variant-of-ExecPrepareExpr-ExecInitExpr.patch === Applying: soft error variant of ExecPrepareExpr, ExecInitExpr === using 'git am' to apply patch ./v2-0003-domain-over-virtual-generated-column.patch === Applying: domain over virtual generated column error: sha1 information is lacking or useless (src/backend/commands/copyfrom.c). error: could not build fake ancestor hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 domain over virtual generated column When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v2-0003-domain-over-virtual-generated-column.patch === patching file src/backend/catalog/heap.c patching file src/backend/commands/copyfrom.c patching file src/backend/commands/tablecmds.c Hunk #1 succeeded at 6011 (offset 2 lines). Hunk #2 succeeded at 6131 (offset 2 lines). Hunk #3 succeeded at 6207 (offset 2 lines). Hunk #4 succeeded at 6252 (offset 2 lines). Hunk #5 succeeded at 6517 (offset 2 lines). patching file src/backend/commands/typecmds.c Hunk #2 FAILED at 128. Hunk #4 FAILED at 2980. Hunk #5 succeeded at 3011 (offset 8 lines). Hunk #6 succeeded at 3139 (offset 13 lines). Hunk #7 succeeded at 3171 (offset 13 lines). Hunk #8 succeeded at 3190 (offset 13 lines). Hunk #9 succeeded at 3236 (offset 13 lines). Hunk #10 succeeded at 3252 (offset 13 lines). Hunk #11 succeeded at 3276 (offset 13 lines). Hunk #12 succeeded at 3319 (offset 18 lines). Hunk #13 FAILED at 3346. Hunk #14 succeeded at 3406 (offset 19 lines). 3 out of 14 hunks FAILED -- saving rejects to file src/backend/commands/typecmds.c.rej patching file src/backend/executor/nodeModifyTable.c Hunk #1 succeeded at 68 (offset 1 line). Hunk #2 succeeded at 417 (offset 1 line). Hunk #3 succeeded at 499 (offset 1 line). Hunk #4 succeeded at 572 (offset 1 line). Hunk #5 succeeded at 590 (offset 1 line). Hunk #6 succeeded at 609 (offset 1 line). Hunk #7 succeeded at 631 (offset 1 line). Hunk #8 succeeded at 974 (offset 1 line). Hunk #9 succeeded at 1102 (offset 1 line). Hunk #10 succeeded at 2190 (offset 3 lines). patching file src/test/regress/expected/fast_default.out patching file src/test/regress/expected/generated_virtual.out Hunk #1 FAILED at 790. 1 out of 1 hunk FAILED -- saving rejects to file src/test/regress/expected/generated_virtual.out.rej patching file src/test/regress/sql/fast_default.sql patching file src/test/regress/sql/generated_virtual.sql Hunk #1 FAILED at 444. 1 out of 1 hunk FAILED -- saving rejects to file src/test/regress/sql/generated_virtual.sql.rej Unstaged changes after reset: M src/backend/catalog/heap.c M src/backend/commands/copyfrom.c M src/backend/commands/tablecmds.c M src/backend/commands/typecmds.c M src/backend/executor/nodeModifyTable.c M src/test/regress/expected/fast_default.out M src/test/regress/sql/fast_default.sql Removing src/backend/commands/typecmds.c.rej Removing src/test/regress/expected/generated_virtual.out.rej Removing src/test/regress/sql/generated_virtual.sql.rej === using 'git apply' to apply patch ./v2-0003-domain-over-virtual-generated-column.patch === Applied patch to 'src/backend/catalog/heap.c' cleanly. error: repository lacks the necessary blob to perform 3-way merge. Falling back to direct application... Applied patch to 'src/backend/commands/tablecmds.c' cleanly. Applied patch to 'src/backend/commands/typecmds.c' with conflicts. error: repository lacks the necessary blob to perform 3-way merge. Falling back to direct application... Applied patch to 'src/test/regress/expected/fast_default.out' cleanly. Applied patch to 'src/test/regress/expected/generated_virtual.out' with conflicts. Applied patch to 'src/test/regress/sql/fast_default.sql' cleanly. Applied patch to 'src/test/regress/sql/generated_virtual.sql' cleanly. U src/backend/commands/typecmds.c U src/test/regress/expected/generated_virtual.out diff --cc src/backend/commands/typecmds.c index 5979580139f,b6f28d41e8d..00000000000 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@@ -126,7 -127,8 +127,12 @@@ static Oid findTypeSubscriptingFunction static Oid findRangeSubOpclass(List *opcname, Oid subtype); static Oid findRangeCanonicalFunction(List *procname, Oid typeOid); static Oid findRangeSubtypeDiffFunction(List *procname, Oid subtype); ++<<<<<<< ours +static void validateDomainCheckConstraint(Oid domainoid, const char *ccbin, LOCKMODE lockmode); ++======= + static void validateDomainCheckConstraint(Oid domainoid, const char *ccbin); + static void DomainNotValidConstrOnVirtual(Oid domainoid, const char *domainName); ++>>>>>>> theirs static void validateDomainNotNullConstraint(Oid domainoid); static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode); static void checkEnumOwner(HeapTuple tup); @@@ -2986,7 -2981,17 +2993,21 @@@ AlterDomainAddConstraint(List *names, N * to. */ if (!constr->skip_validation) ++<<<<<<< ours + validateDomainCheckConstraint(domainoid, ccbin, ShareLock); ++======= + { + /* + * we need updated domain constraint catalog info for validate + * domain check constraints. + */ + CommandCounterIncrement(); + + validateDomainCheckConstraint(domainoid, ccbin); + } + else + DomainNotValidConstrOnVirtual(domainoid, NameStr(typTup->typname)); ++>>>>>>> theirs /* * We must send out an sinval message for the domain, to ensure that @@@ -3248,34 -3355,65 +3381,85 @@@ validateDomainCheckConstraint(Oid domai Datum d; bool isNull; Datum conResult; - Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); - d = slot_getattr(slot, attnum, &isNull); + /* + * compute the virtual generated column expression. + */ + if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + { + /* + * we'll use the EState's per-tuple context for evaluating + * domain check constraint over virtual generated column + * (creating it if it's not already there). + */ + econtext = GetPerTupleExprContext(estate); + + /* Arrange for econtext's scan tuple to be the tuple under test */ + econtext->ecxt_scantuple = slot; + + conResult = ExecEvalExprSwitchContext(ri_GeneratedExprs[i], + econtext, + &isNull); + if (SOFT_ERROR_OCCURRED(ri_GeneratedExprs[i]->escontext)) + { + isNull = true; + ereport(ERROR, + errcode(ERRCODE_CHECK_VIOLATION), + errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint", + NameStr(attr->attname), + RelationGetRelationName(testrel)), + errtablecol(testrel, attnum)); + } + } + else + { + d = slot_getattr(slot, attnum, &isNull); - econtext->domainValue_datum = d; - econtext->domainValue_isNull = isNull; + econtext->domainValue_datum = d; + econtext->domainValue_isNull = isNull; - conResult = ExecEvalExprSwitchContext(exprstate, - econtext, - &isNull); + conResult = ExecEvalExprSwitchContext(exprstate, + econtext, + &isNull); ++<<<<<<< ours + if (!isNull && !DatumGetBool(conResult)) + { + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); + + /* + * In principle the auxiliary information for this error + * should be errdomainconstraint(), but errtablecol() + * seems considerably more useful in practice. Since this + * code only executes in an ALTER DOMAIN command, the + * client should already know which domain is in question, + * and which constraint too. + */ + ereport(ERROR, + (errcode(ERRCODE_CHECK_VIOLATION), + errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint", + NameStr(attr->attname), + RelationGetRelationName(testrel)), + errtablecol(testrel, attnum))); ++======= + if (!isNull && !DatumGetBool(conResult)) + { + /* + * In principle the auxiliary information for this error + * should be errdomainconstraint(), but errtablecol() + * seems considerably more useful in practice. Since this + * code only executes in an ALTER DOMAIN command, the + * client should already know which domain is in question, + * and which constraint too. + */ + ereport(ERROR, + (errcode(ERRCODE_CHECK_VIOLATION), + errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint", + NameStr(attr->attname), + RelationGetRelationName(testrel)), + errtablecol(testrel, attnum))); + } ++>>>>>>> theirs } } diff --cc src/test/regress/expected/generated_virtual.out index dde325e46c6,fb79c2fbac1..00000000000 --- a/src/test/regress/expected/generated_virtual.out +++ b/src/test/regress/expected/generated_virtual.out @@@ -793,33 -790,69 +793,93 @@@ ERROR: relation "gtest23p" does not ex --INSERT INTO gtest23q VALUES (1, 2); -- ok --INSERT INTO gtest23q VALUES (2, 5); -- error -- domains - CREATE DOMAIN gtestdomain1 AS int CHECK (VALUE < 10); - CREATE TABLE gtest24 (a int PRIMARY KEY, b gtestdomain1 GENERATED ALWAYS AS (a * 2) VIRTUAL); - ERROR: virtual generated column "b" cannot have a domain type - --INSERT INTO gtest24 (a) VALUES (4); -- ok - --INSERT INTO gtest24 (a) VALUES (6); -- error + CREATE DOMAIN gtestdomain1 AS int CHECK (VALUE < 10) DEFAULT 12; + CREATE TABLE gtest24 (a int UNIQUE, b gtestdomain1 GENERATED ALWAYS AS (a * 2) VIRTUAL); + INSERT INTO gtest24 (a, b) VALUES (4, default); -- ok + INSERT INTO gtest24 (a) VALUES (3), (NULL); -- ok + INSERT INTO gtest24 (a) VALUES (6); -- error + ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" + UPDATE gtest24 SET a = 6; -- error + ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" + COPY gtest24 FROM stdin; --error + ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" + CONTEXT: COPY gtest24, line 1: "6" + SELECT * FROM gtest24 ORDER BY a; + a | b + ---+--- + 3 | 6 + 4 | 8 + | + (3 rows) + + --ALTER DOMAIN ADD CONSTRAINT variant. + ALTER DOMAIN gtestdomain1 ADD CONSTRAINT cc CHECK (VALUE < 7) NOT VALID; --error + ERROR: can not add NOT VALID constraint for domain "gtestdomain1" + DETAIL: Domain with NOT VALID constraint over virtual generated column are not supported. + ALTER DOMAIN gtestdomain1 ADD CHECK (value IS NULL); --error + ERROR: column "b" of table "gtest24" contains values that violate the new constraint + ALTER DOMAIN gtestdomain1 ADD CHECK (value IS NOT NULL); --error + ERROR: column "b" of table "gtest24" contains values that violate the new constraint + ALTER DOMAIN gtestdomain1 ADD NOT NULL; --error + ERROR: column "b" of table "gtest24" contains null values + DELETE FROM gtest24 WHERE a is NULL; + ALTER DOMAIN gtestdomain1 ADD NOT NULL; --ok + ALTER DOMAIN gtestdomain1 ADD CHECK (value IS NOT NULL); --ok + ALTER DOMAIN gtestdomain1 ADD CHECK (VALUE < 7); --error + ERROR: column "b" of table "gtest24" contains values that violate the new constraint + ALTER DOMAIN gtestdomain1 ADD CHECK (VALUE < 9); --ok CREATE TYPE gtestdomain1range AS range (subtype = gtestdomain1); ++<<<<<<< ours +CREATE TABLE gtest24r (a int PRIMARY KEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 5)) VIRTUAL); +ERROR: virtual generated column "b" cannot have a domain type +--INSERT INTO gtest24r (a) VALUES (4); -- ok +--INSERT INTO gtest24r (a) VALUES (6); -- error +CREATE TABLE gtest24at (a int PRIMARY KEY); +ALTER TABLE gtest24at ADD COLUMN b gtestdomain1 GENERATED ALWAYS AS (a * 2) VIRTUAL; -- error +ERROR: virtual generated column "b" cannot have a domain type +CREATE TABLE gtest24ata (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest24ata ALTER COLUMN b TYPE gtestdomain1; -- error +ERROR: virtual generated column "b" cannot have a domain type +CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); +CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) VIRTUAL); +ERROR: virtual generated column "b" cannot have a domain type +--INSERT INTO gtest24nn (a) VALUES (4); -- ok +--INSERT INTO gtest24nn (a) VALUES (NULL); -- error +-- using user-defined type not yet supported +CREATE TABLE gtest24xxx (a gtestdomain1, b gtestdomain1, c int GENERATED ALWAYS AS (greatest(a, b)) VIRTUAL); -- error +ERROR: generation expression uses user-defined type +LINE 1: ...main1, b gtestdomain1, c int GENERATED ALWAYS AS (greatest(a... + ^ +DETAIL: Virtual generated columns that make use of user-defined types are not yet supported. ++======= + CREATE TABLE gtest24r (a int PRIMARY KEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 4)) VIRTUAL); + INSERT INTO gtest24r (a) VALUES (4); -- ok + INSERT INTO gtest24r (a) VALUES (6); -- error + ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" + INSERT INTO gtest24r (a) VALUES (5); -- error + ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check2" + CREATE TABLE gtest24v ( + a jsonb, + b gtestdomain1[] GENERATED ALWAYS AS (JSON_QUERY(a, '$.a' returning gtestdomain1[] error on error)) VIRTUAL, + c gtestdomain1[] GENERATED ALWAYS AS (JSON_QUERY(a, '$.b' returning gtestdomain1[])) VIRTUAL NOT NULL); + INSERT INTO gtest24v VALUES (jsonb '{"a":[6,10], "b":[6,2]}'); --error + ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" + INSERT INTO gtest24v VALUES (jsonb '{"a":[6,-1], "b":[6,10]}'); --error + ERROR: null value in column "c" of relation "gtest24v" violates not-null constraint + DETAIL: Failing row contains ({"a": [6, -1], "b": [6, 10]}, virtual, virtual). + INSERT INTO gtest24v VALUES (jsonb '{"a":[6,-1], "b":[6,2]}'); --ok + CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); + CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) VIRTUAL); + INSERT INTO gtest24nn (a) VALUES (4); -- ok + INSERT INTO gtest24nn (a) VALUES (NULL); -- error + ERROR: value for domain gtestdomainnn violates check constraint "gtestdomainnn_check" + --ALTER TABLE ADD COLUM variant. + ALTER TABLE gtest24nn ADD COLUMN c gtestdomainnn GENERATED ALWAYS AS (nullif(a, 4)) virtual; --error + ERROR: value for domain gtestdomainnn violates check constraint "gtestdomainnn_check" + ALTER TABLE gtest24nn ADD COLUMN c gtestdomainnn GENERATED ALWAYS AS (a * 3) virtual check (c < 10); --error + ERROR: check constraint "gtest24nn_c_check" of relation "gtest24nn" is violated by some row + ALTER TABLE gtest24nn ADD COLUMN c gtestdomainnn GENERATED ALWAYS AS (a * 2) virtual NOT NULL; --ok ++>>>>>>> theirs -- typed tables (currently not supported) CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); CREATE TABLE gtest28 OF gtest_type (f1 WITH OPTIONS GENERATED ALWAYS AS (f2 *2) VIRTUAL);