diff options
Diffstat (limited to 'src/backend/utils/adt/domains.c')
-rw-r--r-- | src/backend/utils/adt/domains.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c index 3de0cb01a2c..99aeaddb5d2 100644 --- a/src/backend/utils/adt/domains.c +++ b/src/backend/utils/adt/domains.c @@ -126,9 +126,14 @@ domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt) * This is roughly similar to the handling of CoerceToDomain nodes in * execExpr*.c, but we execute each constraint separately, rather than * compiling them in-line within a larger expression. + * + * If escontext points to an ErrorStateContext, any failures are reported + * there, otherwise they are ereport'ed. Note that we do not attempt to do + * soft reporting of errors raised during execution of CHECK constraints. */ static void -domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) +domain_check_input(Datum value, bool isnull, DomainIOData *my_extra, + Node *escontext) { ExprContext *econtext = my_extra->econtext; ListCell *l; @@ -144,11 +149,14 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) { case DOM_CONSTRAINT_NOTNULL: if (isnull) - ereport(ERROR, + { + errsave(escontext, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("domain %s does not allow null values", format_type_be(my_extra->domain_type)), errdatatype(my_extra->domain_type))); + goto fail; + } break; case DOM_CONSTRAINT_CHECK: { @@ -179,13 +187,16 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) econtext->domainValue_isNull = isnull; if (!ExecCheck(con->check_exprstate, econtext)) - ereport(ERROR, + { + errsave(escontext, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("value for domain %s violates check constraint \"%s\"", format_type_be(my_extra->domain_type), con->name), errdomainconstraint(my_extra->domain_type, con->name))); + goto fail; + } break; } default: @@ -200,6 +211,7 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) * per-tuple memory. This avoids leaking non-memory resources, if * anything in the expression(s) has any. */ +fail: if (econtext) ReScanExprContext(econtext); } @@ -213,6 +225,7 @@ domain_in(PG_FUNCTION_ARGS) { char *string; Oid domainType; + Node *escontext = fcinfo->context; DomainIOData *my_extra; Datum value; @@ -245,15 +258,18 @@ domain_in(PG_FUNCTION_ARGS) /* * Invoke the base type's typinput procedure to convert the data. */ - value = InputFunctionCall(&my_extra->proc, - string, - my_extra->typioparam, - my_extra->typtypmod); + if (!InputFunctionCallSafe(&my_extra->proc, + string, + my_extra->typioparam, + my_extra->typtypmod, + escontext, + &value)) + PG_RETURN_NULL(); /* * Do the necessary checks to ensure it's a valid domain value. */ - domain_check_input(value, (string == NULL), my_extra); + domain_check_input(value, (string == NULL), my_extra, escontext); if (string == NULL) PG_RETURN_NULL(); @@ -309,7 +325,7 @@ domain_recv(PG_FUNCTION_ARGS) /* * Do the necessary checks to ensure it's a valid domain value. */ - domain_check_input(value, (buf == NULL), my_extra); + domain_check_input(value, (buf == NULL), my_extra, NULL); if (buf == NULL) PG_RETURN_NULL(); @@ -349,7 +365,7 @@ domain_check(Datum value, bool isnull, Oid domainType, /* * Do the necessary checks to ensure it's a valid domain value. */ - domain_check_input(value, isnull, my_extra); + domain_check_input(value, isnull, my_extra, NULL); } /* |