@@ -126,9 +126,14 @@ domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt)
126
126
* This is roughly similar to the handling of CoerceToDomain nodes in
127
127
* execExpr*.c, but we execute each constraint separately, rather than
128
128
* compiling them in-line within a larger expression.
129
+ *
130
+ * If escontext points to an ErrorStateContext, any failures are reported
131
+ * there, otherwise they are ereport'ed. Note that we do not attempt to do
132
+ * soft reporting of errors raised during execution of CHECK constraints.
129
133
*/
130
134
static void
131
- domain_check_input (Datum value , bool isnull , DomainIOData * my_extra )
135
+ domain_check_input (Datum value , bool isnull , DomainIOData * my_extra ,
136
+ Node * escontext )
132
137
{
133
138
ExprContext * econtext = my_extra -> econtext ;
134
139
ListCell * l ;
@@ -144,11 +149,14 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
144
149
{
145
150
case DOM_CONSTRAINT_NOTNULL :
146
151
if (isnull )
147
- ereport (ERROR ,
152
+ {
153
+ errsave (escontext ,
148
154
(errcode (ERRCODE_NOT_NULL_VIOLATION ),
149
155
errmsg ("domain %s does not allow null values" ,
150
156
format_type_be (my_extra -> domain_type )),
151
157
errdatatype (my_extra -> domain_type )));
158
+ goto fail ;
159
+ }
152
160
break ;
153
161
case DOM_CONSTRAINT_CHECK :
154
162
{
@@ -179,13 +187,16 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
179
187
econtext -> domainValue_isNull = isnull ;
180
188
181
189
if (!ExecCheck (con -> check_exprstate , econtext ))
182
- ereport (ERROR ,
190
+ {
191
+ errsave (escontext ,
183
192
(errcode (ERRCODE_CHECK_VIOLATION ),
184
193
errmsg ("value for domain %s violates check constraint \"%s\"" ,
185
194
format_type_be (my_extra -> domain_type ),
186
195
con -> name ),
187
196
errdomainconstraint (my_extra -> domain_type ,
188
197
con -> name )));
198
+ goto fail ;
199
+ }
189
200
break ;
190
201
}
191
202
default :
@@ -200,6 +211,7 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
200
211
* per-tuple memory. This avoids leaking non-memory resources, if
201
212
* anything in the expression(s) has any.
202
213
*/
214
+ fail :
203
215
if (econtext )
204
216
ReScanExprContext (econtext );
205
217
}
@@ -213,6 +225,7 @@ domain_in(PG_FUNCTION_ARGS)
213
225
{
214
226
char * string ;
215
227
Oid domainType ;
228
+ Node * escontext = fcinfo -> context ;
216
229
DomainIOData * my_extra ;
217
230
Datum value ;
218
231
@@ -245,15 +258,18 @@ domain_in(PG_FUNCTION_ARGS)
245
258
/*
246
259
* Invoke the base type's typinput procedure to convert the data.
247
260
*/
248
- value = InputFunctionCall (& my_extra -> proc ,
249
- string ,
250
- my_extra -> typioparam ,
251
- my_extra -> typtypmod );
261
+ if (!InputFunctionCallSafe (& my_extra -> proc ,
262
+ string ,
263
+ my_extra -> typioparam ,
264
+ my_extra -> typtypmod ,
265
+ escontext ,
266
+ & value ))
267
+ PG_RETURN_NULL ();
252
268
253
269
/*
254
270
* Do the necessary checks to ensure it's a valid domain value.
255
271
*/
256
- domain_check_input (value , (string == NULL ), my_extra );
272
+ domain_check_input (value , (string == NULL ), my_extra , escontext );
257
273
258
274
if (string == NULL )
259
275
PG_RETURN_NULL ();
@@ -309,7 +325,7 @@ domain_recv(PG_FUNCTION_ARGS)
309
325
/*
310
326
* Do the necessary checks to ensure it's a valid domain value.
311
327
*/
312
- domain_check_input (value , (buf == NULL ), my_extra );
328
+ domain_check_input (value , (buf == NULL ), my_extra , NULL );
313
329
314
330
if (buf == NULL )
315
331
PG_RETURN_NULL ();
@@ -349,7 +365,7 @@ domain_check(Datum value, bool isnull, Oid domainType,
349
365
/*
350
366
* Do the necessary checks to ensure it's a valid domain value.
351
367
*/
352
- domain_check_input (value , isnull , my_extra );
368
+ domain_check_input (value , isnull , my_extra , NULL );
353
369
}
354
370
355
371
/*
0 commit comments