mirror of
https://github.com/postgres/postgres.git
synced 2026-03-23 02:43:22 -04:00
Extend DomainHasConstraints() to optionally check constraint volatility
Add an optional bool *has_volatile output parameter to DomainHasConstraints(). When non-NULL, the function checks whether any CHECK constraint contains a volatile expression. Callers that don't need this information pass NULL and get the same behavior as before. This is needed by a subsequent commit that enables the fast default optimization for domains with non-volatile constraints: we can safely evaluate such constraints once at ALTER TABLE time, but volatile constraints require a full table rewrite. Author: Jian He <jian.universality@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andrew Dunstan <andrew@dunslane.net> Reviewed-by: Viktor Holmberg <viktor.holmberg@aiven.io> Discussion: https://postgr.es/m/CACJufxE_+iZBR1i49k_AHigppPwLTJi6km8NOsC7FWvKdEmmXg@mail.gmail.com
This commit is contained in:
parent
a630ac5c20
commit
487cf2cbd2
7 changed files with 32 additions and 9 deletions
|
|
@ -1653,7 +1653,7 @@ BeginCopyFrom(ParseState *pstate,
|
|||
|
||||
Form_pg_attribute att = TupleDescAttr(tupDesc, attno - 1);
|
||||
|
||||
cstate->domain_with_constraint[i] = DomainHasConstraints(att->atttypid);
|
||||
cstate->domain_with_constraint[i] = DomainHasConstraints(att->atttypid, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7531,7 +7531,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|||
defval = (Expr *) build_column_default(rel, attribute->attnum);
|
||||
|
||||
/* Build CoerceToDomain(NULL) expression if needed */
|
||||
has_domain_constraints = DomainHasConstraints(attribute->atttypid);
|
||||
has_domain_constraints = DomainHasConstraints(attribute->atttypid, NULL);
|
||||
if (!defval && has_domain_constraints)
|
||||
{
|
||||
Oid baseTypeId;
|
||||
|
|
@ -14893,7 +14893,7 @@ ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno)
|
|||
{
|
||||
CoerceToDomain *d = (CoerceToDomain *) expr;
|
||||
|
||||
if (DomainHasConstraints(d->resulttype))
|
||||
if (DomainHasConstraints(d->resulttype, NULL))
|
||||
return true;
|
||||
expr = (Node *) d->arg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5061,6 +5061,6 @@ ExecInitJsonCoercion(ExprState *state, JsonReturning *returning,
|
|||
scratch.d.jsonexpr_coercion.exists_cast_to_int = exists_coerce &&
|
||||
getBaseType(returning->typid) == INT4OID;
|
||||
scratch.d.jsonexpr_coercion.exists_check_domain = exists_coerce &&
|
||||
DomainHasConstraints(returning->typid);
|
||||
DomainHasConstraints(returning->typid, NULL);
|
||||
ExprEvalPushStep(state, &scratch);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4039,7 +4039,7 @@ eval_const_expressions_mutator(Node *node,
|
|||
arg = eval_const_expressions_mutator((Node *) cdomain->arg,
|
||||
context);
|
||||
if (context->estimate ||
|
||||
!DomainHasConstraints(cdomain->resulttype))
|
||||
!DomainHasConstraints(cdomain->resulttype, NULL))
|
||||
{
|
||||
/* Record dependency, if this isn't estimation mode */
|
||||
if (context->root && !context->estimate)
|
||||
|
|
|
|||
|
|
@ -4628,7 +4628,7 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
|
|||
if (jsexpr->returning->typid != TEXTOID)
|
||||
{
|
||||
if (get_typtype(jsexpr->returning->typid) == TYPTYPE_DOMAIN &&
|
||||
DomainHasConstraints(jsexpr->returning->typid))
|
||||
DomainHasConstraints(jsexpr->returning->typid, NULL))
|
||||
jsexpr->use_json_coercion = true;
|
||||
else
|
||||
jsexpr->use_io_coercion = true;
|
||||
|
|
|
|||
27
src/backend/utils/cache/typcache.c
vendored
27
src/backend/utils/cache/typcache.c
vendored
|
|
@ -1485,10 +1485,14 @@ UpdateDomainConstraintRef(DomainConstraintRef *ref)
|
|||
/*
|
||||
* DomainHasConstraints --- utility routine to check if a domain has constraints
|
||||
*
|
||||
* Returns true if the domain has any constraints at all. If has_volatile
|
||||
* is not NULL, also checks whether any CHECK constraint contains a volatile
|
||||
* expression and sets *has_volatile accordingly.
|
||||
*
|
||||
* This is defined to return false, not fail, if type is not a domain.
|
||||
*/
|
||||
bool
|
||||
DomainHasConstraints(Oid type_id)
|
||||
DomainHasConstraints(Oid type_id, bool *has_volatile)
|
||||
{
|
||||
TypeCacheEntry *typentry;
|
||||
|
||||
|
|
@ -1498,7 +1502,26 @@ DomainHasConstraints(Oid type_id)
|
|||
*/
|
||||
typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
|
||||
|
||||
return (typentry->domainData != NULL);
|
||||
if (typentry->domainData == NULL)
|
||||
return false;
|
||||
|
||||
if (has_volatile)
|
||||
{
|
||||
*has_volatile = false;
|
||||
|
||||
foreach_node(DomainConstraintState, constrstate,
|
||||
typentry->domainData->constraints)
|
||||
{
|
||||
if (constrstate->constrainttype == DOM_CONSTRAINT_CHECK &&
|
||||
contain_volatile_functions((Node *) constrstate->check_expr))
|
||||
{
|
||||
*has_volatile = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ extern void InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref,
|
|||
|
||||
extern void UpdateDomainConstraintRef(DomainConstraintRef *ref);
|
||||
|
||||
extern bool DomainHasConstraints(Oid type_id);
|
||||
extern bool DomainHasConstraints(Oid type_id, bool *has_volatile);
|
||||
|
||||
extern TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue