barrel_bql_lower (barrel_docdb v1.1.1)
View SourceCanonicalize and validate BQL ASTs; lower them to executable plans (lowering lands with the planner step).
Canonical form: - paths are range-variable tagged: {path, Loc, base | unnest, Comps} with Comps in the engine shape [binary() | integer() | '*'] and the leading alias stripped (PartiQL name resolution for one binding: the range variable shadows same-named document fields); - parameters are substituted; - operands are normalized (literal OP path is flipped, constant and path-to-path predicates are rejected); - BETWEEN is expanded to comparisons; - NOT is eliminated by dualization, so downstream code never sees a 'not' node. The engine evaluates leaves as exists-and-satisfies (absent path => false), which matches SQL WHERE except under NOT; dualizing keeps PartiQL's missing-is-filtered semantics. Negations survive only as flags on in/like/contains, which the planner guards with {exists, Path}; - the top-level conjunction is flattened to a list.
Summary
Types
-type canon() :: #{select := star | [projection()], source := {collection, loc(), binary()} | {table_fn, loc(), binary(), [barrel_bql_ast:fn_arg()]}, alias := binary(), unnest := undefined | #{path := cpath(), alias := binary(), loc := loc()}, where := [cexpr()], order_by := [{cpath(), asc | desc}], limit := undefined | {integer, loc(), non_neg_integer()}, offset := undefined | {integer, loc(), non_neg_integer()}, subscribe := boolean()}.
-type cexpr() :: {cmp, loc(), '=' | '!=' | '<' | '<=' | '>' | '>=', cpath(), clit()} | {is_null, loc(), cpath(), boolean()} | {is_missing, loc(), cpath(), boolean()} | {in, loc(), cpath(), [clit()], boolean()} | {like, loc(), cpath(), binary(), boolean()} | {contains, loc(), cpath(), clit(), boolean()} | {'and', loc(), cexpr(), cexpr()} | {'or', loc(), cexpr(), cexpr()}.
-type loc() :: barrel_bql_ast:loc().
-type plan() :: #{spec := map(), source := {collection, binary()} | {table_fn, vector_top_k | bm25_top_k | hybrid_top_k, #{query := binary(), k := pos_integer(), ef_search => pos_integer()}}, unnest := undefined | #{path := comps(), alias := binary()}, post := #{residual := [term()], doc_where := [term()], order := undefined | {project_key(), asc | desc}, offset := non_neg_integer(), limit := undefined | pos_integer(), project := star | [{b | u | score, comps() | binary(), binary()}], empty := boolean()}, subscribe := boolean(), streamable := boolean(), warnings := [term()]}.
-type var() :: base | unnest.