Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 963e8b9

Browse files
jianhe-funCommitfest Bot
authored and
Commitfest Bot
committed
domain over virtual generated column
domains that don't have constraints work just fine. domain constraints check happen within ExecComputeGenerated. we compute the virtual generated column in ExecComputeGenerated and discarded the value. if value cannot coerce to domain then we will error out. domain_with_constaint can be element type of range, multirange, array, composite. To be bulletproof, if this column type is not type of TYPTYPE_BASE or it's an array type, then we do actually compute the virtual generated expression. This can have negative performance for some INSERTs. The following two query shows in pg_catalog, most of the system type is TYPTYPE_BASE. So I guess this compromise is fine. select count(*),typtype from pg_type where typnamespace = 'pg_catalog'::regnamespace group by 2 order by 1 desc; ALTER DOMAIN ADD CONSTRAINT is supported for virtual generated column. ALTER TABLE ADD VIRTUAL GENERATED COLUMN. need table scan to verify new column generation expression value satisfied the domain constraints. but no need table rewrite. discussion: https://postgr.es/m/CACJufxFNUHxuSE=g20C2aLO3d+4T_j9h0x8esMirzcC4FrLbBg@mail.gmail.com
1 parent d563931 commit 963e8b9

File tree

9 files changed

+459
-78
lines changed

9 files changed

+459
-78
lines changed

src/backend/catalog/heap.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -583,17 +583,6 @@ CheckAttributeType(const char *attname,
583583
}
584584
else if (att_typtype == TYPTYPE_DOMAIN)
585585
{
586-
/*
587-
* Prevent virtual generated columns from having a domain type. We
588-
* would have to enforce domain constraints when columns underlying
589-
* the generated column change. This could possibly be implemented,
590-
* but it's not.
591-
*/
592-
if (flags & CHKATYPE_IS_VIRTUAL)
593-
ereport(ERROR,
594-
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
595-
errmsg("virtual generated column \"%s\" cannot have a domain type", attname));
596-
597586
/*
598587
* If it's a domain, recurse to check its base type.
599588
*/

src/backend/commands/copyfrom.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,9 +1343,10 @@ CopyFrom(CopyFromState cstate)
13431343
}
13441344
else
13451345
{
1346-
/* Compute stored generated columns */
1346+
/* Compute generated columns */
13471347
if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
1348-
resultRelInfo->ri_RelationDesc->rd_att->constr->has_generated_stored)
1348+
(resultRelInfo->ri_RelationDesc->rd_att->constr->has_generated_stored ||
1349+
resultRelInfo->ri_RelationDesc->rd_att->constr->has_generated_virtual))
13491350
ExecComputeGenerated(resultRelInfo, estate, myslot,
13501351
CMD_INSERT);
13511352

src/backend/commands/tablecmds.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6009,7 +6009,7 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
60096009
* rebuild data.
60106010
*/
60116011
if (tab->constraints != NIL || tab->verify_new_notnull ||
6012-
tab->partition_constraint != NULL)
6012+
tab->newvals || tab->partition_constraint != NULL)
60136013
ATRewriteTable(tab, InvalidOid);
60146014

60156015
/*
@@ -6129,6 +6129,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
61296129
BulkInsertState bistate;
61306130
int ti_options;
61316131
ExprState *partqualstate = NULL;
6132+
List *domain_virtual_attrs = NIL;
61326133

61336134
/*
61346135
* Open the relation(s). We have surely already locked the existing
@@ -6204,6 +6205,16 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
62046205

62056206
/* expr already planned */
62066207
ex->exprstate = ExecInitExpr((Expr *) ex->expr, NULL);
6208+
if (tab->rewrite == 0 && ex->is_generated)
6209+
{
6210+
Form_pg_attribute attr = TupleDescAttr(newTupDesc, ex->attnum - 1);
6211+
if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL &&
6212+
DomainHasConstraints(attr->atttypid))
6213+
{
6214+
Assert(!attr->attisdropped);
6215+
domain_virtual_attrs = lappend_int(domain_virtual_attrs, attr->attnum);
6216+
}
6217+
}
62076218
}
62086219

62096220
notnull_attrs = notnull_virtual_attrs = NIL;
@@ -6239,6 +6250,13 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
62396250
needscan = true;
62406251
}
62416252

6253+
/*
6254+
* We need verify domain constraints on the virtual generated column are
6255+
* satisfied, which requires table scan.
6256+
*/
6257+
if (domain_virtual_attrs != NIL)
6258+
needscan = true;
6259+
62426260
if (newrel || needscan)
62436261
{
62446262
ExprContext *econtext;
@@ -6497,6 +6515,35 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
64976515
}
64986516
}
64996517

6518+
/*
6519+
* domain_virtual_attrs is a list of newly added columns that are
6520+
* virtual generated columns with a domain data type and associated
6521+
* constraints. We need to verify that these domain constraints are
6522+
* satisfied.
6523+
*/
6524+
if (domain_virtual_attrs != NIL)
6525+
{
6526+
Assert(tab->rewrite == 0);
6527+
6528+
foreach(l, tab->newvals)
6529+
{
6530+
NewColumnValue *ex = lfirst(l);
6531+
6532+
if (!ex->is_generated)
6533+
continue;
6534+
6535+
if(list_member_int(domain_virtual_attrs, ex->attnum) &&
6536+
!ExecCheck(ex->exprstate, econtext))
6537+
{
6538+
Form_pg_attribute attr = TupleDescAttr(newTupDesc, ex->attnum - 1);
6539+
ereport(ERROR,
6540+
errcode(ERRCODE_CHECK_VIOLATION),
6541+
errmsg("value for domain %s is violated by some row",
6542+
format_type_be(attr->atttypid)));
6543+
}
6544+
}
6545+
}
6546+
65006547
if (partqualstate && !ExecCheck(partqualstate, econtext))
65016548
{
65026549
if (tab->validate_default)

0 commit comments

Comments
 (0)