Re: ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1
От | Richard Guo |
---|---|
Тема | Re: ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1 |
Дата | |
Msg-id | CAMbWs48Jcw-NvnxT23WiHP324wG44DvzcH1j4hc0Zn+3sR9cfg@mail.gmail.com обсуждение исходный текст |
Ответ на | Re: ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1 (Tom Lane <tgl@sss.pgh.pa.us>) |
Ответы |
Re: ERROR: wrong varnullingrels (b 3) (expected (b)) for Var 2/1
|
Список | pgsql-hackers |
On Wed, Jun 14, 2023 at 6:02 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
I wrote:
> Richard Guo <guofenglinux@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
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
В списке pgsql-hackers по дате отправления:
Предыдущее
От: Etsuro FujitaДата:
Сообщение: Re: postgres_fdw: wrong results with self join + enable_nestloop off