mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Fix handling of some SQL/JSON locations in query jumbling
GetJsonBehaviorConst() builds Const values for clauses like ON EMPTY or
ON ERROR in SQL/JSON, and was setting up a location without considering
the fact that these are not constants as per the query text: they are
query keywords. For example "EMPTY ARRAY ON EMPTY" became "$2 ARRAY ON
EMPTY", leading to confusing information reported for example in PGSS.
The Const nodes used by GetJsonBehaviorConst() is now left unset. The
location was only used for an error position. This code path cannot be
reached currently but we cannot use the expression location if not set;
this spot is switched to the location of behavior keyword instead, which
is better than nothing.
This is obviously a bug. Unfortunately, no backpatch is done as this
impacts the information of saved in PGSS and the shape of the Nodes
themselves.
Oversight in 6185c9737c.
Author: Ilya Staroverov <i.staroverov@ftdata.ru>
Reviewed-by: Sami Imseih <samimseih.pg@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/457969A9-5D24-422F-B09E-F388053DE028@localhost.localdomain
This commit is contained in:
@@ -72,11 +72,11 @@ SELECT JSON_VALUE(js, '$.a' DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR) FROM pgss_sql
|
||||
SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls;
|
||||
calls | query
|
||||
-------+-----------------------------------------------------------------------------------------
|
||||
2 | SELECT JSON_VALUE(js, $1 $2 ON EMPTY ERROR ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_VALUE(js, $1 DEFAULT $2 ON EMPTY DEFAULT $3 ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_VALUE(js, $1 DEFAULT $2 ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_VALUE(js, $1 DEFAULT $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_VALUE(js, $1 ERROR ON EMPTY $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_VALUE(js, $1 ERROR ON EMPTY NULL ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_VALUE(js, $1 NULL ON EMPTY ERROR ON ERROR) FROM pgss_sqljson_tab
|
||||
3 | SELECT JSON_VALUE(js, $1) FROM pgss_sqljson_tab
|
||||
1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t
|
||||
(7 rows)
|
||||
@@ -219,19 +219,19 @@ SELECT JSON_QUERY(js, '$.a' EMPTY ARRAY ON EMPTY EMPTY OBJECT ON ERROR)
|
||||
(0 rows)
|
||||
|
||||
SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls;
|
||||
calls | query
|
||||
-------+---------------------------------------------------------------------
|
||||
1 | SELECT JSON_QUERY(js, $1 $2 ARRAY ON EMPTY $3 OBJECT ON ERROR) +
|
||||
| FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_QUERY(js, $1 $2 ARRAY ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 $2 OBJECT ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 $2 OBJECT ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 $2 ON EMPTY) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_QUERY(js, $1 $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
calls | query
|
||||
-------+-----------------------------------------------------------------------
|
||||
1 | SELECT JSON_QUERY(js, $1 DEFAULT $2 ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 DEFAULT $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 EMPTY ARRAY ON EMPTY EMPTY OBJECT ON ERROR) +
|
||||
| FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_QUERY(js, $1 EMPTY ARRAY ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 EMPTY OBJECT ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 EMPTY OBJECT ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_QUERY(js, $1 EMPTY ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 ERROR ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 ERROR ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_QUERY(js, $1 NULL ON EMPTY) FROM pgss_sqljson_tab
|
||||
1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t
|
||||
(11 rows)
|
||||
|
||||
@@ -429,13 +429,13 @@ SELECT JSON_EXISTS(js, '$.a ? (@ > $x)' PASSING 2 AS x) FROM pgss_sqljson_tab;
|
||||
(0 rows)
|
||||
|
||||
SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls;
|
||||
calls | query
|
||||
-------+------------------------------------------------------------------
|
||||
1 | SELECT JSON_EXISTS(js, $1 $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_EXISTS(js, $1 $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_EXISTS(js, $1 $2 ON ERROR) FROM pgss_sqljson_tab
|
||||
calls | query
|
||||
-------+-------------------------------------------------------------------
|
||||
1 | SELECT JSON_EXISTS(js, $1 ERROR ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_EXISTS(js, $1 FALSE ON ERROR) FROM pgss_sqljson_tab
|
||||
2 | SELECT JSON_EXISTS(js, $1 PASSING $2 AS x) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_EXISTS(js, $1 TRUE ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT JSON_EXISTS(js, $1 UNKNOWN ON ERROR) FROM pgss_sqljson_tab
|
||||
1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t
|
||||
(6 rows)
|
||||
|
||||
@@ -995,7 +995,7 @@ SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls;
|
||||
calls | query
|
||||
-------+-------------------------------------------------------------------
|
||||
3 | SELECT * FROM pgss_sqljson_tab, +
|
||||
| JSON_TABLE(js, $1 COLUMNS (a int PATH '$.a') $2 ON ERROR) jt
|
||||
| JSON_TABLE(js, $1 COLUMNS (a int PATH '$.a') EMPTY ON ERROR) jt
|
||||
1 | SELECT * FROM pgss_sqljson_tab, +
|
||||
| JSON_TABLE(js, $1 COLUMNS (a int PATH '$.a') ERROR ON ERROR) jt
|
||||
2 | SELECT * FROM pgss_sqljson_tab, +
|
||||
|
||||
@@ -99,7 +99,7 @@ static JsonBehavior *transformJsonBehavior(ParseState *pstate, JsonExpr *jsexpr,
|
||||
JsonBehavior *behavior,
|
||||
JsonBehaviorType default_behavior,
|
||||
JsonReturning *returning);
|
||||
static Node *GetJsonBehaviorConst(JsonBehaviorType btype, int location);
|
||||
static Node *GetJsonBehaviorConst(JsonBehaviorType btype);
|
||||
static Node *make_row_comparison_op(ParseState *pstate, List *opname,
|
||||
List *largs, List *rargs, int location);
|
||||
static Node *make_row_distinct_op(ParseState *pstate, List *opname,
|
||||
@@ -4897,7 +4897,7 @@ transformJsonBehavior(ParseState *pstate, JsonExpr *jsexpr,
|
||||
}
|
||||
|
||||
if (expr == NULL && btype != JSON_BEHAVIOR_ERROR)
|
||||
expr = GetJsonBehaviorConst(btype, location);
|
||||
expr = GetJsonBehaviorConst(btype);
|
||||
|
||||
/*
|
||||
* Try to coerce the expression if needed.
|
||||
@@ -4988,7 +4988,7 @@ transformJsonBehavior(ParseState *pstate, JsonExpr *jsexpr,
|
||||
errmsg("cannot cast behavior expression of type %s to %s",
|
||||
format_type_be(exprType(expr)),
|
||||
format_type_be(returning->typid)),
|
||||
parser_errposition(pstate, exprLocation(expr)));
|
||||
parser_errposition(pstate, location));
|
||||
}
|
||||
|
||||
expr = coerced_expr;
|
||||
@@ -5010,7 +5010,7 @@ transformJsonBehavior(ParseState *pstate, JsonExpr *jsexpr,
|
||||
* JsonBehaviorType.
|
||||
*/
|
||||
static Node *
|
||||
GetJsonBehaviorConst(JsonBehaviorType btype, int location)
|
||||
GetJsonBehaviorConst(JsonBehaviorType btype)
|
||||
{
|
||||
Datum val = (Datum) 0;
|
||||
Oid typid = JSONBOID;
|
||||
@@ -5065,7 +5065,6 @@ GetJsonBehaviorConst(JsonBehaviorType btype, int location)
|
||||
}
|
||||
|
||||
con = makeConst(typid, -1, InvalidOid, len, val, isnull, isbyval);
|
||||
con->location = location;
|
||||
|
||||
return (Node *) con;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user