oqx 0.13.0

OQX (omgbase Query eXpressions): a composable query language and engine for JSON-shaped collections — Rust implementation
Documentation
# oqx

**OQX (omgbase Query eXpressions) — Rust implementation.**

OQX is a small query language for querying JSON-shaped collections — arrays of
records, nested relations, recursive trees — with a readable, declarative
syntax:

```text
select name, id, title
from people
where jobs exists { where employer == "Globocorp" && !end_date }
```

This crate is the second implementation of the language. The reference
implementation is the TypeScript package
[`@omgbase/oqx`](https://github.com/omgbase/omgbase/tree/main/packages/oqx).
Both conform to the language-neutral specification and fixtures at
[`spec/oqx`](https://github.com/omgbase/omgbase/tree/main/spec/oqx) in the same
repository, and each reports the spec version it conforms to.

## Status

Conformance-first, and conformant: `tests/spec.rs` runs every fixture in
`spec/oqx/cases` (850 cases in 29 files at language version 0.13) and all of them
pass, so `cargo test -p oqx` requires every case to pass. Published on crates.io
as `oqx`.

The runner keeps an allowlist mechanism for the periods when the spec runs
ahead of the port (from `spec/oqx/README.md`): if `tests/spec-passing.txt`
exists, it names the case ids (`<file-stem>::<name>`, one per line) that must
pass; a listed case that fails fails the build, an unlisted case that passes
fails the build with a message asking for it to be added, and a listed id that
no longer exists is an error too. When the file is absent — the current state —
every case must pass. `cargo test -p oqx` prints `spec: N passed, M failed, K
listed` on stderr and, on failure, the offending case ids grouped by fixture
file with a one-line reason each.

To (re)generate the allowlist from the currently passing set — for example
after new fixtures land in `spec/oqx/cases` before the port catches up — run:

```sh
OQX_SPEC_UPDATE=1 cargo test -p oqx --test spec
```

This writes the list (and prints any listed case that now fails, so nothing is
blessed silently), or deletes the file once every case passes.

## Layering

Mirrors the reference so the two can be read side by side:

- `lexer` / `parser` → `ast` — the fixed clause order (`select, from, where,
  follow, order by, limit, offset`; only a leading `select` may drop its
  keyword) and the expression grammar.
- `semantics` — the scalar contract every backend obeys: typed equality with no
  coercion, absent-aware ordering (absent sorts last both ways), membership,
  ranges, arithmetic, builtins.
- `regex_dialect` — `matches()`: the spec's regex baseline parsed and rewritten
  for the `regex` crate (`\d`→`[0-9]`, `\b`→`(?-u:\b)`, `\s`→one listed set,
  flags→`(?ims)`), so a pattern means the same here as in the reference;
  `DataContext::regex_dialect()` / `DefaultContext::with_regex_dialect` opt a
  host into the crate's native syntax instead (not portable).
- `engine` — the in-memory engine over a `DataContext` (the seam that binds the
  language to a data model; the default context is plain `Value`s).
- `planner` — the seam for pushing work into a store and finishing the residual
  in memory.

## Features

- `json` — `From`/`Into` between `oqx::Value` and `serde_json::Value`.
- `sqlite` — `adapters::sqlite::SqliteTable`, a `QueryPlanner` that pushes the
  flat query core (scan + translatable conjunctive predicates, `LIMIT` for
  unordered `first`/`single`) into SQL over a bundled SQLite via `rusqlite`,
  leaving the rest to the in-memory residual. Implies `json`.

## License

MIT