From 336124160b13cecdfa3824d7a3df8143bf93081e Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Tue, 1 Sep 2026 22:55:13 +0300 Subject: [PATCH v1] postgres_fdw: Fix "may be used uninitialized" warning in foreign_join_ok() Commit 0ee83dd4a99 detected the mixed foreign x function-RTE cases in one if/else chain that only set a pair of bool flags, then acted on those flags in a second chain. fpinfo_o and fpinfo_i are each assigned in one chain and read in the other, so proving them initialized requires correlating the flags with the assignments. gcc 13 with -Og does not manage that and reports fpinfo_i as possibly uninitialized; clang's -Wconditional-uninitialized likewise reports both variables. The flags served no purpose beyond deferring the work, so merge the two chains and read both fdw_private pointers up front, unconditionally. A function rel never has an fdw_private of its own, so the pointer is simply NULL until the stub replaces it, and each branch now assigns and uses the two variables in one place. Reported-by: Karina Litskevich Reported-by: Marina Polyakova Discussion: https://postgr.es/m/CACiT8iamoL-%3D792e6JK2uCVvwDhfCg7DXHhvqN0P33jhGg2-8A%40mail.gmail.com --- contrib/postgres_fdw/postgres_fdw.c | 53 +++++++++++------------------ 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 9269418a074..47197a733ff 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -7044,8 +7044,6 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, PgFdwRelationInfo *fpinfo_i; ListCell *lc; List *joinclauses; - bool outer_is_function = false; - bool inner_is_function = false; /* * We support pushing down INNER, LEFT, RIGHT, FULL OUTER and SEMI joins. @@ -7069,40 +7067,22 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, * function RTE can be absorbed into joins on multiple foreign servers * (each call gets its own stub fpinfo and rechecks shippability for the * specific server). + * + * A function rel has no fdw_private of its own, so when one side is a + * function RTE we replace its NULL fpinfo with a stub, and the rest of + * this function and the cost estimator can then treat both sides + * uniformly. We hand the stub to the joinrel's deparser via the same + * path the foreign side uses, but we never permanently attach it to the + * function rel's fdw_private (different joinrels may pair the same + * function RTE with different foreign servers). */ fpinfo = (PgFdwRelationInfo *) joinrel->fdw_private; + fpinfo_o = (PgFdwRelationInfo *) outerrel->fdw_private; + fpinfo_i = (PgFdwRelationInfo *) innerrel->fdw_private; + if (jointype == JOIN_INNER && innerrel->rtekind == RTE_FUNCTION && - (fpinfo_o = (PgFdwRelationInfo *) outerrel->fdw_private) && - fpinfo_o->pushdown_safe && + fpinfo_o && fpinfo_o->pushdown_safe && function_rte_pushdown_ok(root, innerrel, outerrel)) - { - inner_is_function = true; - } - else if (jointype == JOIN_INNER && outerrel->rtekind == RTE_FUNCTION && - (fpinfo_i = (PgFdwRelationInfo *) innerrel->fdw_private) && - fpinfo_i->pushdown_safe && - function_rte_pushdown_ok(root, outerrel, innerrel)) - { - outer_is_function = true; - } - else - { - fpinfo_o = (PgFdwRelationInfo *) outerrel->fdw_private; - fpinfo_i = (PgFdwRelationInfo *) innerrel->fdw_private; - if (!fpinfo_o || !fpinfo_o->pushdown_safe || - !fpinfo_i || !fpinfo_i->pushdown_safe) - return false; - } - - /* - * If one side is a function RTE, allocate a stub fpinfo so the rest of - * this function and the cost estimator can treat it uniformly. We hand - * the stub to the joinrel's deparser via the same path the foreign side - * uses, but we never permanently attach it to the function rel's - * fdw_private (different joinrels may pair the same function RTE with - * different foreign servers). - */ - if (inner_is_function) { fpinfo_i = init_func_stub_fpinfo(fpinfo_o, innerrel); @@ -7117,15 +7097,20 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, &fpinfo_i->remote_conds, &fpinfo_i->local_conds); fpinfo->inner_func_fpinfo = fpinfo_i; } - else if (outer_is_function) + else if (jointype == JOIN_INNER && outerrel->rtekind == RTE_FUNCTION && + fpinfo_i && fpinfo_i->pushdown_safe && + function_rte_pushdown_ok(root, outerrel, innerrel)) { fpinfo_o = init_func_stub_fpinfo(fpinfo_i, outerrel); - /* See the comment in the inner_is_function branch above. */ + /* See the comment in the branch above. */ classifyConditions(root, outerrel, fpinfo_o, outerrel->baserestrictinfo, &fpinfo_o->remote_conds, &fpinfo_o->local_conds); fpinfo->outer_func_fpinfo = fpinfo_o; } + else if (!fpinfo_o || !fpinfo_o->pushdown_safe || + !fpinfo_i || !fpinfo_i->pushdown_safe) + return false; /* * If joining relations have local conditions, those conditions are -- 2.55.0