Arangox.Query (Arangox v0.8.0)

Copy Markdown View Source

An AQL query: the statement, and the options the server should run it under.

A query is what Arangox.query/4 runs and what Arangox.cursor/4 streams.

There is no prepare step

ArangoDB has no prepared statements, and DBConnection.prepare/3 is refused here rather than implemented. What the server offers instead is a plan cache: a memoisation of parsing and planning, held server-side, keyed by statement text, and shared by every caller in the database.

That shape matters, because it is not the one the word "prepare" implies. The first execution populates an entry; the second reports the key of the entry that served it; changing a bind value reuses the same entry, since the plan is parameterised over values. The reuse therefore comes from running the same text again, and nothing a client holds on to participates in it.

So the plan cache is asked for per query, and only when asked:

Arangox.query(conn, "FOR d IN c FILTER d.x == @x RETURN d", %{x: 1},
  use_plan_cache: true)

It is opt-in rather than defaulted for two reasons. The server refuses to cache some statements outright — an UPSERT is refused with 1584, :query_not_eligible_for_plan_caching — and the option has a server-version floor of 3.12.4 that this driver gates on. Neither belongs to a caller who never asked for the cache.

Deliberately holds no database. Plans are cached per database, so a query that captured one could not be reused against another; the database is a property of the request, not of the statement.

Options

AQL options are given as snake_case atoms and mapped to the names the HTTP API uses. The mapping is taken from the server's own published OpenAPI document, which is also what decides whether an option belongs at the top level of the request body or inside its options object — :batch_size is top-level, :full_count is nested, and nothing about the name says which.

Arangox.cursor(conn, "FOR i IN 1..100 RETURN i", %{}, batch_size: 10)

%Arangox.Query{query: "FOR i IN 1..100 RETURN i", opts: [full_count: true]}

An option this module does not know is an error rather than a key invented on the wire, because the server ignores unknown body attributes silently and a typo would otherwise look like it worked.

:properties remains the escape hatch: a list or map of body attributes passed through verbatim under the names the server uses. It is merged last, so it wins over a mapped option. That ordering is what keeps code written against the escape hatch working unchanged when a mapped name for the same field arrives later.

Summary

Types

t()

@type t() :: %Arangox.Query{opts: keyword(), query: binary()}