@@ -4284,13 +4284,12 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
42844284memset (& jsestate -> error ,0 ,sizeof (NullableDatum ));
42854285memset (& jsestate -> empty ,0 ,sizeof (NullableDatum ));
42864286
4287- /*
4288- * Also reset ErrorSaveContext contents for the next row. Since we don't
4289- * set details_wanted, we don't need to also reset error_data, which would
4290- * be NULL anyway.
4291- */
4292- Assert (!jsestate -> escontext .details_wanted &&
4293- jsestate -> escontext .error_data == NULL );
4287+ /* Also reset ErrorSaveContext contents for the next row. */
4288+ if (jsestate -> escontext .details_wanted )
4289+ {
4290+ jsestate -> escontext .error_data = NULL ;
4291+ jsestate -> escontext .details_wanted = false;
4292+ }
42944293jsestate -> escontext .error_occurred = false;
42954294
42964295switch (jsexpr -> op )
@@ -4400,6 +4399,14 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
44004399error = true;
44014400}
44024401
4402+ /*
4403+ * When setting up the ErrorSaveContext (if needed) for capturing the
4404+ * errors that occur when coercing the JsonBehavior expression, set
4405+ * details_wanted to be able to show the actual error message as the
4406+ * DETAIL of the error message that tells that it is the JsonBehavior
4407+ * expression that caused the error; see ExecEvalJsonCoercionFinish().
4408+ */
4409+
44034410/* Handle ON EMPTY. */
44044411if (empty )
44054412{
@@ -4410,13 +4417,19 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
44104417if (jsexpr -> on_empty -> btype != JSON_BEHAVIOR_ERROR )
44114418{
44124419jsestate -> empty .value = BoolGetDatum (true);
4420+ /* Set up to catch coercion errors of the ON EMPTY value. */
4421+ jsestate -> escontext .error_occurred = false;
4422+ jsestate -> escontext .details_wanted = true;
44134423Assert (jsestate -> jump_empty >=0 );
44144424return jsestate -> jump_empty ;
44154425}
44164426}
44174427else if (jsexpr -> on_error -> btype != JSON_BEHAVIOR_ERROR )
44184428{
44194429jsestate -> error .value = BoolGetDatum (true);
4430+ /* Set up to catch coercion errors of the ON ERROR value. */
4431+ jsestate -> escontext .error_occurred = false;
4432+ jsestate -> escontext .details_wanted = true;
44204433Assert (!throw_error && jsestate -> jump_error >=0 );
44214434return jsestate -> jump_error ;
44224435}
@@ -4442,6 +4455,9 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
44424455* op -> resvalue = (Datum )0 ;
44434456* op -> resnull = true;
44444457jsestate -> error .value = BoolGetDatum (true);
4458+ /* Set up to catch coercion errors of the ON ERROR value. */
4459+ jsestate -> escontext .error_occurred = false;
4460+ jsestate -> escontext .details_wanted = true;
44454461return jsestate -> jump_error ;
44464462}
44474463
@@ -4544,9 +4560,33 @@ ExecEvalJsonCoercion(ExprState *state, ExprEvalStep *op,
45444560 (Node * )escontext );
45454561}
45464562
4563+ static char *
4564+ GetJsonBehaviorValueString (JsonBehavior * behavior )
4565+ {
4566+ /*
4567+ * The order of array elements must correspond to the order of
4568+ * JsonBehaviorType members.
4569+ */
4570+ const char * behavior_names []=
4571+ {
4572+ "NULL" ,
4573+ "ERROR" ,
4574+ "EMPTY" ,
4575+ "TRUE" ,
4576+ "FALSE" ,
4577+ "UNKNOWN" ,
4578+ "EMPTY ARRAY" ,
4579+ "EMPTY OBJECT" ,
4580+ "DEFAULT"
4581+ };
4582+
4583+ return pstrdup (behavior_names [behavior -> btype ]);
4584+ }
4585+
45474586/*
45484587 * Checks if an error occurred in ExecEvalJsonCoercion(). If so, this sets
4549- * JsonExprState.error to trigger the ON ERROR handling steps.
4588+ * JsonExprState.error to trigger the ON ERROR handling steps, unless the
4589+ * error is thrown when coercing a JsonBehavior value.
45504590 */
45514591void
45524592ExecEvalJsonCoercionFinish (ExprState * state ,ExprEvalStep * op )
@@ -4555,15 +4595,37 @@ ExecEvalJsonCoercionFinish(ExprState *state, ExprEvalStep *op)
45554595
45564596if (SOFT_ERROR_OCCURRED (& jsestate -> escontext ))
45574597{
4598+ /*
4599+ * jsestate->error or jsetate->empty being set means that the error
4600+ * occurred when coercing the JsonBehavior value. Throw the error in
4601+ * that case with the actual coercion error message shown in the
4602+ * DETAIL part.
4603+ */
4604+ if (DatumGetBool (jsestate -> error .value ))
4605+ ereport (ERROR ,
4606+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
4607+ errmsg ("could not coerce ON ERROR expression (%s) to the RETURNING type" ,
4608+ GetJsonBehaviorValueString (jsestate -> jsexpr -> on_error )),
4609+ errdetail ("%s" ,jsestate -> escontext .error_data -> message )));
4610+ else if (DatumGetBool (jsestate -> empty .value ))
4611+ ereport (ERROR ,
4612+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
4613+ errmsg ("could not coerce ON EMPTY expression (%s) to the RETURNING type" ,
4614+ GetJsonBehaviorValueString (jsestate -> jsexpr -> on_empty )),
4615+ errdetail ("%s" ,jsestate -> escontext .error_data -> message )));
4616+
45584617* op -> resvalue = (Datum )0 ;
45594618* op -> resnull = true;
4619+
45604620jsestate -> error .value = BoolGetDatum (true);
45614621
45624622/*
45634623 * Reset for next use such as for catching errors when coercing a
45644624 * JsonBehavior expression.
45654625 */
45664626jsestate -> escontext .error_occurred = false;
4627+ jsestate -> escontext .error_occurred = false;
4628+ jsestate -> escontext .details_wanted = true;
45674629}
45684630}
45694631