On Wed, Feb 18, 2026 at 7:54 AM David Rowley <dgrowleyml@gmail.com> wrote:
> On Wed, 18 Feb 2026 at 00:31, PG Bug reporting form
> <noreply@postgresql.org> wrote:
> > create table a (id int, x_id int, y_id int);
> > insert into a values (1, 1, 1), (1, 2, 2), (1, 3, 3);
> > create table x (id int, nm text, constraint pk_x_id primary key (id));
> > insert into x values (1, 'x1'), (2, 'x2'), (3, 'x3');
> > create table y (id int, nm text, constraint pk_y_id primary key (id));
> > insert into y values (1, 'y1'), (3, 'y3'), (4, 'y4');
> >
> > select a.id, z.id
> > from a
> > join x on x.id = a.x_id
> > left join y on y.id = a.y_id
> > join lateral(select x.id
> > union all
> > select y.id) z on z.id is not null;
> Thanks for the reproducer.
>
> I'd say that y.id Var in the lateral join should be getting marked as
> nullable by the left join, but it's not being marked as nullable by
> anything.
Exactly. I think this is because when adjust_appendrel_attrs_mutator
propagates the nullingrel bits from the parent rel's Var into the
translated Var, it loses the translated Var's original bits. Instead
of overwriting the translated Var's nullingrels, I think we should
merge them.
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -291,8 +291,11 @@ adjust_appendrel_attrs_mutator(Node *node,
var->varattno, get_rel_name(appinfo->parent_reloid));
if (IsA(newnode, Var))
{
- ((Var *) newnode)->varreturningtype = var->varreturningtype;
- ((Var *) newnode)->varnullingrels = var->varnullingrels;
+ Var *newvar = (Var *) newnode;
+
+ newvar->varreturningtype = var->varreturningtype;
+ newvar->varnullingrels = bms_add_members(newvar->varnullingrels,
+ var->varnullingrels);
}
- Richard