On Wed, Jun 14, 2023 at 6:02 AM Tom Lane <t...@sss.pgh.pa.us> wrote:
> I wrote: > > Richard Guo <guofengli...@gmail.com> writes: > >> Oh, wait ... It occurred to me that we may have this same issue with > >> Memoize cache keys. > > > Good catch --- I'll take a closer look tomorrow. > > Pushed after a little more fiddling with the comments. I just realized that we may still have holes in this area. Until now we're mainly focusing on LATERAL subquery, in which case the lateral reference Vars are copied into rel->subplan_params and we've already adjusted the nulling bitmaps there. But what about the lateral reference Vars in other cases? In extract_lateral_references() we consider 5 cases, /* Fetch the appropriate variables */ if (rte->rtekind == RTE_RELATION) vars = pull_vars_of_level((Node *) rte->tablesample, 0); else if (rte->rtekind == RTE_SUBQUERY) vars = pull_vars_of_level((Node *) rte->subquery, 1); else if (rte->rtekind == RTE_FUNCTION) vars = pull_vars_of_level((Node *) rte->functions, 0); else if (rte->rtekind == RTE_TABLEFUNC) vars = pull_vars_of_level((Node *) rte->tablefunc, 0); else if (rte->rtekind == RTE_VALUES) vars = pull_vars_of_level((Node *) rte->values_lists, 0); else { Assert(false); return; /* keep compiler quiet */ } We've handled the second case, i.e., RTE_SUBQUERY. It's not hard to compose a query for each of the other 4 cases that shows that we need to adjust the nulling bitmaps for them too. 1. RTE_RELATION with tablesample explain (costs off) select * from int8_tbl t1 left join int8_tbl t2 on true left join lateral (select * from int8_tbl t3 TABLESAMPLE SYSTEM (t2.q1)) s on t2.q1 = 1; ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1 2. RTE_FUNCTION explain (costs off) select * from int8_tbl t1 left join int8_tbl t2 on true left join lateral (select * from generate_series(t2.q1, 100)) s on t2.q1 = 1; ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1 3. RTE_TABLEFUNC explain (costs off) select * from xmltest2 t1 left join xmltest2 t2 on true left join lateral xmltable('/d/r' PASSING t2.x COLUMNS a int) on t2._path = 'a'; ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1 4. RTE_VALUES explain (costs off) select * from int8_tbl t1 left join int8_tbl t2 on true left join lateral (select q1 from (values(t2.q1), (t2.q1)) v(q1)) s on t2.q1 = 1; ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1 So it seems that we need to do nullingrel adjustments in a more common place. Also, there might be lateral references in the tlist, so the query below is supposed to also encounter the 'wrong varnullingrels' error. explain (costs off) select * from int8_tbl t1 left join int8_tbl t2 on true left join lateral (select t2.q1 from int8_tbl t3) s on t2.q1 = 1; server closed the connection unexpectedly But as we can see, it triggers the Assert in try_nestloop_path. /* If we got past that, we shouldn't have any unsafe outer-join refs */ Assert(!have_unsafe_outer_join_ref(root, outerrelids, inner_paramrels)); I think it exposes a new issue. It seems that we extract a problematic lateral_relids from lateral references within PlaceHolderVars in create_lateral_join_info. I doubt that we should use ph_lateral directly. It seems more reasonable to me that we strip outer-join relids from ph_lateral and then use that for lateral_relids. Any thoughts? Thanks Richard