Skip to content

query: Negative contains/glob filters are false when the field is absent, contrary to intuition #4

@PaluMacil

Description

@PaluMacil

This requires a decision.

In filter.go, filterOpNegContains and filterOpNegGlob both return false when the field is absent:
goif seg.filterOp == filterOpNegContains {
    fv := fieldValue(v, seg.name)
    if fv == nil {
        return false  // <-- surprising
    }
Semantically, [Tags!~devops] reads as "Tags does not contain devops". If the element doesn't have a Tags field at all, most users would expect that to be true (it certainly doesn't contain devops). Today it's treated as false — absent fields fail negative filters.
This matters for mixed-type slices where some element types have the field and others don't. ..[Status!=retired] on a slice of heterogeneous records silently drops records that don't even have a Status field.
Before changing anything, write tests for:

[Tags!~devops] with an element missing the Tags field — should match (absence means no devops tag)
[Status!=retired] with an element missing Status — should match
Corresponding positive cases: [Tags~devops] with absent Tags — should NOT match (already correct)
[Status=active] with absent Status — should NOT match (already correct)

Confirm the negative cases fail today. Decide and document: does "absent = negative filter passes" apply to ALL negative forms (!!, !=, !~)? Currently !! does match-on-absence. Make != and !~ consistent with !!. Update the README to state this invariant explicitly: "negative filters (!!, !=, !~) treat missing fields as matching; positive filters treat missing fields as non-matching."

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