From: | BharatDB <bharatdbpg(at)gmail(dot)com> |
---|---|
To: | pgsql-hackers(at)lists(dot)postgresql(dot)org, pgsql-hackers(at)postgresql(dot)org |
Subject: | Reduce "Var IS [NOT] NULL" quals during constant folding |
Date: | 2025-08-28 13:01:55 |
Message-ID: | CAAh00ETEMEXntw1gxp=xP+4sqrz80tK1R4VEhTpqH9CJpxs-wA@mail.gmail.com |
Views: | Whole Thread | Raw Message | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
*Subject:* Contribution Interest – Bug Fix on Reducing "Var IS [NOT] NULL"
Quals During Constant Folding
Dear Team,
I hope this message finds you well.
With reference to the conversation ongioing in message ID:
(CAMbWs487wxHq0fUu+Cew7Y+n+wpY_B--PT-61syXrE40uZqErw
<https://www.postgresql.org/message-id/CAMbWs487wxHq0fUu%2BCew7Y%2Bn%2BwpY_B--PT-61syXrE40uZqErw%40mail.gmail.com>
,
I am writing to express my interest in contributing to the ongoing work on
fixing the bug related to reducing “Var IS [NOT] NULL” quals during
constant folding. As part of my initial efforts, I have been exploring the
planner code paths and introducing an approach to gather early catalog
information for base relations.
Specifically, I have implemented the following:
-
Preprocessing Relation RTEs
-
Added a new static function preprocess_relation_rtes() in
src/backend/optimizer/plan/planner.c to collect attribute-level metadata
(e.g., NOT NULL, generated columns, inheritance flags) at an early stage.
-
Hash Table for Attribute Info
-
Defined a new planner-local hash table (relattrinfo_htab) for storing
per-attribute information.
-
Created a supporting header (src/include/optimizer/relattrinfo.h) and
implementation file (src/backend/optimizer/util/relattrinfo.c).
-
Planner Integration
-
Initialized the attribute info hash table in subquery_planner().
-
Ensured preprocessing is invoked before pull_up_sublinks().
-
Optimization Step
-
Extended the constant folding path to check stored attribute metadata
during IS [NOT] NULL qual simplification, allowing safe reduction to
constant true/false where applicable.
1. Declare - *preprocess_relation_rtes()*
File: in subquery_planner() inside *src/backend/optimizer/plan/planner.c*.
-
Insert your new step *before* pull_up_sublinks().
*Snippet:*
/* * Do preprocessing of RTEs before we pull up sublinks */
preprocess_relation_rtes(root);
2.Create a new static function *preprocess_relation_rtes()* in planner.c:
File: *src/backend/optimizer/plan/planner.c*
*Snippet:*
/* * preprocess_relation_rtes * Gather early catalog info for each
base relation * (NOT NULL attrs, generated cols, inheritance flags).
*/static void preprocess_relation_rtes(PlannerInfo *root){ ListCell
*lc; Relation rel;
foreach(lc, root->parse->rtable) { RangeTblEntry *rte =
(RangeTblEntry *) lfirst(lc);
if (rte->rtekind == RTE_RELATION) { rel =
table_open(rte->relid, AccessShareLock);
/* Collect attnotnull info */ TupleDesc tupdesc
= RelationGetDescr(rel); for (int attno = 0; attno <
tupdesc->natts; attno++) { Form_pg_attribute
attr = TupleDescAttr(tupdesc, attno); if
(!attr->attisdropped) { if
(attr->attnotnull) store_notnull_info(root,
rte->relid, attno + 1);
if (attr->attgenerated)
store_generated_info(root, rte->relid, attno + 1); }
}
/* Inheritance flag */ if
(rel->rd_rel->relhassubclass) store_inh_info(root,
rte->relid);
table_close(rel, AccessShareLock); } }
}
3. Filename* – **src/include/nodes/pathnodes.h*
*Snippet:*
typedef struct PlannerInfo
{
HTAB *relattrinfo_htab; /* plannerlocal cache of attr metadata */
} PlannerInfo;
4. Create a new header.
Location: *src/include/optimizer/relattrinfo.h*
*Snippet: *
#ifndef RELATTRINFO_H
#define RELATTRINFO_H
#include "postgres.h"
#include "utils/hsearch.h"
/* key for hash table */
typedef struct RelAttrInfoKey
{
Oid relid; /* relation OID */
AttrNumber attno; /* attribute number (1-based) */
} RelAttrInfoKey;
/* value stored in hash table */
typedef struct RelAttrInfoEntry
{
RelAttrInfoKey key;
bool notnull;
bool generated;
} RelAttrInfoEntry;
extern HTAB *create_relattrinfo_htab(void);
#endif /* RELATTRINFO_H */
5. Created a new file.
Location: *src/backend/optimizer/util/relattrinfo.c*
*Snippet:*
#include "postgres.h"
#include "optimizer/relattrinfo.h"
HTAB *create_relattrinfo_htab(void)
{
HASHCTL ctl;
memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(RelAttrInfoKey);
ctl.entrysize = sizeof(RelAttrInfoEntry);
return hash_create("Planner relattr info cache",
128, /* initial size */
&ctl,
HASH_ELEM | HASH_BLOBS);
}
6. File: *src/backend/optimizer/plan/planner.c* in *subquery_planner()*
(this runs before most rewrites).
*Snippet:*
*/** Create hash table for early attr info */
root->relattrinfo_htab = create_relattrinfo_htab();
/* Collect early info before pull_up_sublinks */
preprocess_relation_rtes(root);
7. *C**reate**d** a hash table*
File: *src/backend/optimizer/plan/planner.c*
*Example:*
typedef struct RelAttrInfoKey{ Oid relid; AttrNumber attno;}
RelAttrInfoKey;
typedef struct RelAttrInfoEntry{ RelAttrInfoKey key; bool
notnull; bool generated;} RelAttrInfoEntry;
Initialize it in *subquery_planner()*:
root->relattrinfo_htab = create_relattrinfo_htab();
8. Constant folding
if (IsA(arg, Var)){ Var *var = (Var *) arg; if
(lookup_notnull_info(root, var->varno, var->varattno)) { if
(ntest->nulltesttype == IS_NOT_NULL) return (Expr *)
makeBoolConst(true, false); else return (Expr *)
makeBoolConst(false, false); }}
With this groundwork, my plan is to continue refining the approach,
validating correctness against inheritance cases, and ensuring
compliance with planner invariants. I would also like to engage with
reviewers to align this with the broader design direction.
Please let me know how best I can proceed with submitting my patch for
review and contributing further to this fix.
Thank you for your time and consideration.
Best Regards,
Soumya
From | Date | Subject | |
---|---|---|---|
Next Message | Andrew Jackson | 2025-08-28 13:05:34 | Re: Adding pg_dump flag for parallel export to pipes |
Previous Message | Konstantin Knizhnik | 2025-08-28 12:57:27 | Re: Non-reproducible AIO failure |