@@ -4284,13 +4284,12 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
4284
4284
memset (& jsestate -> error , 0 , sizeof (NullableDatum ));
4285
4285
memset (& jsestate -> empty , 0 , sizeof (NullableDatum ));
4286
4286
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
+ }
4294
4293
jsestate -> escontext .error_occurred = false;
4295
4294
4296
4295
switch (jsexpr -> op )
@@ -4400,6 +4399,14 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
4400
4399
error = true;
4401
4400
}
4402
4401
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
+
4403
4410
/* Handle ON EMPTY. */
4404
4411
if (empty )
4405
4412
{
@@ -4410,13 +4417,19 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
4410
4417
if (jsexpr -> on_empty -> btype != JSON_BEHAVIOR_ERROR )
4411
4418
{
4412
4419
jsestate -> 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;
4413
4423
Assert (jsestate -> jump_empty >= 0 );
4414
4424
return jsestate -> jump_empty ;
4415
4425
}
4416
4426
}
4417
4427
else if (jsexpr -> on_error -> btype != JSON_BEHAVIOR_ERROR )
4418
4428
{
4419
4429
jsestate -> 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;
4420
4433
Assert (!throw_error && jsestate -> jump_error >= 0 );
4421
4434
return jsestate -> jump_error ;
4422
4435
}
@@ -4442,6 +4455,9 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
4442
4455
* op -> resvalue = (Datum ) 0 ;
4443
4456
* op -> resnull = true;
4444
4457
jsestate -> 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;
4445
4461
return jsestate -> jump_error ;
4446
4462
}
4447
4463
@@ -4544,9 +4560,33 @@ ExecEvalJsonCoercion(ExprState *state, ExprEvalStep *op,
4544
4560
(Node * ) escontext );
4545
4561
}
4546
4562
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
+
4547
4586
/*
4548
4587
* 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.
4550
4590
*/
4551
4591
void
4552
4592
ExecEvalJsonCoercionFinish (ExprState * state , ExprEvalStep * op )
@@ -4555,15 +4595,37 @@ ExecEvalJsonCoercionFinish(ExprState *state, ExprEvalStep *op)
4555
4595
4556
4596
if (SOFT_ERROR_OCCURRED (& jsestate -> escontext ))
4557
4597
{
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
+
4558
4617
* op -> resvalue = (Datum ) 0 ;
4559
4618
* op -> resnull = true;
4619
+
4560
4620
jsestate -> error .value = BoolGetDatum (true);
4561
4621
4562
4622
/*
4563
4623
* Reset for next use such as for catching errors when coercing a
4564
4624
* JsonBehavior expression.
4565
4625
*/
4566
4626
jsestate -> escontext .error_occurred = false;
4627
+ jsestate -> escontext .error_occurred = false;
4628
+ jsestate -> escontext .details_wanted = true;
4567
4629
}
4568
4630
}
4569
4631
0 commit comments