Skip to content

A cidr or varchar column prunes no chunk groups, because its key is treated as cross-type against inet or text #1433

Closed

Description

@OffgridwithJD

Found reviewing #1426, whose cd (cidr) range arm removes 0 chunk groups where the same values as inet remove 5. A sequel to #477: that fix added a cross-type path, and binary-coercible types fall through it.

The measurement

On PG17 at main, 12 row groups of contiguous values:

column type predicate Usable Skip Predicates Zone Map Probes chunk groups removed
inet range over a contiguous run 2 12 5 of 12
cidr, same values same range 0 0 0
varchar(20) vc BETWEEN '003005' AND '009005' 0 0 0

Both columns have complete zone maps (12 of 12, min and max). EXPLAIN still counts the filter in Columnar Pushed-Down Filters, which is #479's point. Answers are correct, because the executor rechecks the qual; the cost is a full read of the column.

Cause

A comparison on a cidr column resolves to inet >= inet. The planner side strips the RelabelType, so the scan key reaches pgcolumnar_make_predicates (src/columnar_reader.c) with a column of type cidr and an argument subtype of inet.

  • getBaseType() doesn't unify binary-coercible types, so crossType is true (columnar_reader.c:885).
  • GetDefaultOpClass(cidr, btree) gives inet_ops, family network_ops.
  • get_opfamily_proc(network_ops, cidr, inet, BTORDER_PROC) finds nothing, because network_ops registers only (inet, inet). The code hits continue and drops the key.

varchar against text is the same case: text_ops registers (text, text), not (varchar, text).

Suggested fix

When the column type or the argument type is binary-coercible to the opclass's input type (get_opclass_input_type, IsBinaryCoercible), compare both as that type: treat the key as same-type and use the opclass's ordinary order proc. A test should cover cidr, varchar and a domain over each, both pruning and the answers against heap.

🤖 Generated with Claude Code

Activity

  1. jdatcmd commented on Oct 15, 2026

    @jdatcmd
    Collaborator

    @OffgridwithJD, I'm taking this one too, unless you've already started; if you have, say so and I'll drop it. My plan:

    1. Red first, both twins. Add cidr, varchar and a domain over each to a covered pruning suite. For each one: chunk groups removed (inet's and text's own counts are the controls), and the answer against heap.
    2. The fix, as you suggested: when a side is binary-coercible to the opclass input type, compare both sides as that type through the ordinary order proc. I'll also check whether the same drop happens anywhere else in the zone-map code, such as the bloom or interval checks.
    3. The PG15 to 19 matrix.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions