AshNeo4j.QueryHelper (AshNeo4j v0.10.0)

Copy Markdown View Source

AshNeo4j DataLayer QueryHelper

Summary

Functions

Renders an update's changeset.filter guard (the "only-update-if" predicate, #361) to {:ok, conditions} for the update WHERE, or {:error, %AshNeo4j.Error.UnsupportedUpdateFilter{}} when it can't be rendered in full.

Queries nodes, using Ash.Query

Renders changeset.atomics (a keyword of {field, Ash.Expr}, #361) into {:ok, {set_expressions, params}} for the update SET, where each entry is "n.<prop> = <cypher>" evaluated against the live node — or {:error, %AshNeo4j.Error.UnsupportedAtomic{}} when an expression can't be rendered.

Resolves a hop chain to {:ok, {[{edge_label, direction, dest_label}], reached_resource}}, threading the current resource so relationship-name hops resolve at each step. reached_resource is nil once an explicit-edge hop breaks the resource chain.

Functions

guard_conditions(mapping, filter)

@spec guard_conditions(AshNeo4j.ResourceMapping.t(), Ash.Filter.t() | nil) ::
  {:ok, list()} | {:error, struct()}

Renders an update's changeset.filter guard (the "only-update-if" predicate, #361) to {:ok, conditions} for the update WHERE, or {:error, %AshNeo4j.Error.UnsupportedUpdateFilter{}} when it can't be rendered in full.

Stance: never under-guard. The guard is only pushed down when the filter is a conjunction (and-only — no or/not) of supported attribute predicates that each render; a calculation ref or any predicate the pushdown drops makes the whole guard unsupported, so the data layer returns rather than applies the update unguarded. nil (no guard) is {:ok, []}.

query_nodes(ash_query)

@spec query_nodes(struct()) :: {:error, any()} | {:ok, any()}

Queries nodes, using Ash.Query

render_atomic_sets(resource, mapping, atomics)

@spec render_atomic_sets(module(), AshNeo4j.ResourceMapping.t(), keyword()) ::
  {:ok, {[binary()], map()}} | {:error, struct()}

Renders changeset.atomics (a keyword of {field, Ash.Expr}, #361) into {:ok, {set_expressions, params}} for the update SET, where each entry is "n.<prop> = <cypher>" evaluated against the live node — or {:error, %AshNeo4j.Error.UnsupportedAtomic{}} when an expression can't be rendered.

Renders: arithmetic (+ - * /), comparisons, if/3 (⇒ CASE), string concat (<>+) and string_trim (⇒ trim, Ash's string cast), attribute refs (n.<prop>) and scalar literals — numbers/strings/booleans/nil, and atoms (e.g. Ash.Type.Atom enum values) bound as their stored string form. An expression node it doesn't cover (e.g. another Ash function) is refused rather than mis-written (stance a). Param keys are am_-prefixed and threaded across all atomics so they stay unique.

resolve_chain(resource, chain)

@spec resolve_chain(module(), list()) ::
  {:ok, {[{atom(), atom(), atom() | nil}], module() | nil}}
  | {:error, {:unresolved_hop, term()}}

Resolves a hop chain to {:ok, {[{edge_label, direction, dest_label}], reached_resource}}, threading the current resource so relationship-name hops resolve at each step. reached_resource is nil once an explicit-edge hop breaks the resource chain.

Returns {:error, {:unresolved_hop, hop}} when a relationship-name hop names no declared relate edge (so it can't be a Cypher edge label) — instead of silently using the name as the label (#342). Public so read-time consumers (e.g. the projection calculation) can turn a chain opt into Cypher path segments for Cypher.Query.related_nodes/4.