1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

SQL/JSON: Fix issues with DEFAULT .. ON ERROR / EMPTY

SQL/JSON query functions allow specifying an expression to return
when either of ON ERROR or ON EMPTY condition occurs when evaluating
the JSON path expression.  The parser (transformJsonBehavior()) checks
that the specified expression is one of the supported expressions, but
there are two issues with how the check is done that are fixed in this
commit:

* No check for some expressions related to coercion, such as
  CoerceViaIO, that may appear in the transformed user-specified
  expressions that include cast(s)

* An unsupported expression may be masked by a coercion-related
  expression, which must be flagged by checking the latter's
  argument expression recursively

Author: Jian He <jian.universality@gmail.com>
Author: Amit Langote <amitlangote09@gmail.com>
Reported-by: Jian He <jian.universality@gmail.com>
Discussion: https://postgr.es/m/CACJufxEqhqsfrg_p7EMyo5zak3d767iFDL8vz_4%3DZBHpOtrghw@mail.gmail.com
Discussion: https://postgr.es/m/CACJufxGOerH1QJknm1noh-Kz5FqU4p7QfeZSeVT2tN_4SLXYNg@mail.gmail.com
This commit is contained in:
Amit Langote
2024-04-18 14:46:35 +09:00
parent b4fad46b6b
commit c0fc075186
5 changed files with 167 additions and 2 deletions

View File

@ -4616,6 +4616,40 @@ coerceJsonExprOutput(ParseState *pstate, JsonExpr *jsexpr)
(jsexpr->use_io_coercion != jsexpr->use_json_coercion));
}
/*
* Recursively checks if the given expression, or its sub-node in some cases,
* is valid for using as an ON ERROR / ON EMPTY DEFAULT expression.
*/
static bool
ValidJsonBehaviorDefaultExpr(Node *expr, void *context)
{
if (expr == NULL)
return false;
switch (nodeTag(expr))
{
/* Acceptable expression nodes */
case T_Const:
case T_FuncExpr:
case T_OpExpr:
return true;
/* Acceptable iff arg of the following nodes is one of the above */
case T_CoerceViaIO:
case T_CoerceToDomain:
case T_ArrayCoerceExpr:
case T_ConvertRowtypeExpr:
case T_RelabelType:
case T_CollateExpr:
return expression_tree_walker(expr, ValidJsonBehaviorDefaultExpr,
context);
default:
break;
}
return false;
}
/*
* Transform a JSON BEHAVIOR clause.
*/
@ -4636,8 +4670,7 @@ transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior,
if (btype == JSON_BEHAVIOR_DEFAULT)
{
expr = transformExprRecurse(pstate, behavior->expr);
if (!IsA(expr, Const) && !IsA(expr, FuncExpr) &&
!IsA(expr, OpExpr))
if (!ValidJsonBehaviorDefaultExpr(expr, NULL))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("can only specify a constant, non-aggregate function, or operator expression for DEFAULT"),