unreleased

0.2.0 (2026-08-23)

Added

  • Nested fields. An unquoted dotted field name is a path: first.second: foo yields one nested node per dot, wrapping the comparison at the leaf, and the operator travels down with it.

    %{"type" => "nested", "path" => "first",
      "term" => %{"type" => "comparison", "field" => "second", "operator" => "=", ...}}

    nested recurses through "term", the same convention not and group already use, so an existing walker descends it without changes. Empty segments are rejected (a., a..b), and a leading dot or digit still cannot start a field name.

  • Quoted field names: "first.second": foo. Quoting makes the name literal — its dots are characters, not separators — so it stays a plain comparison with "field" => "first.second". This is how you address a field whose name genuinely contains dots, and it also allows characters an unquoted name cannot hold, such as spaces.

  • Bracketed value lists: field:[a,b] is equivalent to field:(a OR b) and produces the same value_list AST. Whitespace around the comma is optional, elements may be quoted or globs, and a single-element list (field:[a]) is valid.

  • The nested-object form: first: { second: foo and third: bar }, which produces the same nested nodes the dotted form does — a:{b:c} and a.b:c are the same AST. Bodies may hold any expression, nest further (a:{b:{c:d}}), and take a quoted or dotted path.

Fixed

  • Underscored the unused error and acc bindings in the generated parser. Regenerating lib/kql.ex emitted nine warnings, which mix compile --warnings-as-errors rejects. These are reapplied by hand after each mix compile.nimble run.

Notes

One breaking change: { and } join \, (, ), :, <, >, " and * as characters that must be quoted or escaped in an unquoted value. A character cannot be structural and an ordinary value character at once, which is the same reason parens have always been excluded. This matches Kibana, whose grammar defines SpecialCharacter = [\\():<>"*{}] — kql's set was that one minus the braces, only because nested queries were unsupported.

So make:a{b}c parsed in 0.1.0 and is now an error; write make:"a{b}c" or make:a\{b\}c.

Otherwise every query valid in 0.1.0 parses to the same AST. Dotted and quoted field names did not parse at all in 0.1.0, so a nested node cannot appear for any query that previously worked: an undotted make:foo is still a bare comparison.

Because [, ] and , remain legal unquoted-value characters, a value that merely looks like a list keeps parsing as a value: field:[a]x is the value [a]x, and an unclosed field:[a,b is the value [a,b. A bracketed list is recognised only when nothing else follows the closing bracket. Inside a list, a literal , or ] must be quoted or escaped, as a literal paren already must be inside ( ... ).

0.1.0 (2025-11-25)

  • Initial release