From c0fc0751862d4e9b7ca9d51f2cd79344690ec873 Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Thu, 18 Apr 2024 14:46:35 +0900 Subject: 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 Author: Amit Langote Reported-by: Jian He Discussion: https://postgr.es/m/CACJufxEqhqsfrg_p7EMyo5zak3d767iFDL8vz_4%3DZBHpOtrghw@mail.gmail.com Discussion: https://postgr.es/m/CACJufxGOerH1QJknm1noh-Kz5FqU4p7QfeZSeVT2tN_4SLXYNg@mail.gmail.com --- src/backend/parser/parse_expr.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'src/backend/parser/parse_expr.c') diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 34ac17868b5..1c1c86aa3e9 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -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"), -- cgit v1.2.3