diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 1e42d75465..bd01ec0526 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -1084,8 +1084,10 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) /* * Simplify constant expressions. For function RTEs, this was already - * done by preprocess_function_rtes ... but we have to do it again if the - * RTE is LATERAL and might have contained join alias variables. + * done by preprocess_function_rtes. (But note we must do it again for + * EXPRKIND_RTFUNC_LATERAL, because those might by now contain + * un-simplified subexpressions inserted by flattening of subqueries or + * join alias variables.) * * Note: an essential effect of this is to convert named-argument function * calls to positional notation and insert the current actual values of @@ -1099,8 +1101,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) * careful to maintain AND/OR flatness --- that is, do not generate a tree * with AND directly under AND, nor OR directly under OR. */ - if (!(kind == EXPRKIND_RTFUNC || - (kind == EXPRKIND_RTFUNC_LATERAL && !root->hasJoinRTEs))) + if (kind != EXPRKIND_RTFUNC) expr = eval_const_expressions(root, expr); /* diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index cafca1f9ae..2334a1321e 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -2416,3 +2416,32 @@ select *, row_to_json(u) from unnest(array[]::rngfunc2[]) u; (0 rows) drop type rngfunc2; +-- check handling of functions pulled up into function RTEs (bug #17227) +explain (verbose, costs off) +select * from + (select jsonb_path_query_array(module->'lectures', '$[*]') as lecture + from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb]) + as unnested_modules(module)) as ss, + jsonb_to_recordset(ss.lecture) as j (id text); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: jsonb_path_query_array((unnested_modules.module -> 'lectures'::text), '$[*]'::jsonpath, '{}'::jsonb, false), j.id + -> Function Scan on pg_catalog.unnest unnested_modules + Output: unnested_modules.module + Function Call: unnest('{"{\"lectures\": [{\"id\": \"1\"}]}"}'::jsonb[]) + -> Function Scan on pg_catalog.jsonb_to_recordset j + Output: j.id + Function Call: jsonb_to_recordset(jsonb_path_query_array((unnested_modules.module -> 'lectures'::text), '$[*]'::jsonpath, '{}'::jsonb, false)) +(8 rows) + +select * from + (select jsonb_path_query_array(module->'lectures', '$[*]') as lecture + from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb]) + as unnested_modules(module)) as ss, + jsonb_to_recordset(ss.lecture) as j (id text); + lecture | id +---------------+---- + [{"id": "1"}] | 1 +(1 row) + diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index 3c436028da..7e5cde14c4 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -767,3 +767,18 @@ select *, row_to_json(u) from unnest(array[null::rngfunc2, (1,'foo')::rngfunc2, select *, row_to_json(u) from unnest(array[]::rngfunc2[]) u; drop type rngfunc2; + +-- check handling of functions pulled up into function RTEs (bug #17227) + +explain (verbose, costs off) +select * from + (select jsonb_path_query_array(module->'lectures', '$[*]') as lecture + from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb]) + as unnested_modules(module)) as ss, + jsonb_to_recordset(ss.lecture) as j (id text); + +select * from + (select jsonb_path_query_array(module->'lectures', '$[*]') as lecture + from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb]) + as unnested_modules(module)) as ss, + jsonb_to_recordset(ss.lecture) as j (id text);