Skip to content

Mango match_failures/2 function - #6080

Open
jcoglan wants to merge 17 commits into
mainfrom
mango-match-failures
Open

Mango match_failures/2 function#6080
jcoglan wants to merge 17 commits into
mainfrom
mango-match-failures

Conversation

@jcoglan

@jcoglan jcoglan commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This PR has the same content as #5858, it is just in a branch in the apache repo to see if this resolves problems with CI.

jcoglan added 17 commits July 31, 2026 17:01
Rather than returning a boolean to indicate just success or failure,
`mango_selector:match/2` now returns a list of "failures" describing the
ways in which the selector failed to match the input. If this list is
empty, the match was a success.
We will need to pass other things around between `match` calls as well
the current `Cmp` function, so here we replace this argument with a
`#ctx` record that intially just contains a `cmp` field.
To give detailed feedback to the caller, the `#ctx` argument to
`mango_selector:match/3` now records the path that was taken to reach
each value, and this path is added to the `#failure` records.

Each path segment is either a binary, if it represents an object
property, or an integer if it represents an array index. Items are
pushed on the front of `#ctx.path` as this is faster than pushing onto
the back of a list. This list can then be reversed once the final list
of failures has been generated, before the failures are presented to the
caller.
Collecting detailed `#failure` records rather than a boolean true/false
when evaluating selectors imposes a performance penalty, so we would
like to only do this when a selector is used for a VDU, not when it is
used for indexing/filtering.

To this end we introduce "verbose" mode signalled via the `#ctx.verbose`
field, and each branch of `mango_selector:match/3` now has 3 distinct
versions:

- `#ctx{verbose = false}`: this is the original version that returns
  true/false, taken when a selector is used for Mango queries.

- `#ctx{verbose = true, negate = false}`: verbose mode, when the
  operator is not negated by an enclosing `$not` operator. Returns a
  list of `#failure` records which may be empty.

- `#ctx{verbose = true, negate = true}`: verbose mode, when the operator
  is negated by an enclosing `$not` operator. Returns a list of
  `#failure` records.

The different negation modes are needed because, in order to generate
meaningful failure messages, we need to record whether an operator was
negated. The behaviour of combinators like `$and`, `$or`, `$allMatch`
and `$elemMatch` means not all `$not` operators can be normalized out of
the selector before evaluation. Instead, when we encounter a `$not`
during evaluation, we flip the `#ctx.negate` field before evaluating the
inner operator.
Until now, document updates rejected by a Mango VDU returned an opaque
"forbidden" message to the client. This commit adds a detailed list of
failures, obtained by converting the `#failure` records returned by
`mango_selector:match/3` into human-readable messages.
Currently, when a design doc is updated, we validate the `map` and
`reduce` fields, but not `validate_doc_update`. Instead, trying to
update any other doc while an invalid `validate_doc_update` exists will
trigger an error.

This comment makes VDU validation more 'eager' by performing it when the
ddoc itself is updated. Normal doc writes will still trigger an error if
an invalid `validate_doc_update` already exists, but now we try to
prevent this happening by validating VDUs when they are first created.
…keyMapMatch") should be considered successful when applied to values of the wrong type
@jcoglan
jcoglan force-pushed the mango-match-failures branch from 5404017 to 200cbda Compare July 31, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant