AshAge.Cypher.Parameterized (AshAge v1.0.1)

Copy Markdown View Source

Parameterized Cypher query builder for Apache AGE.

AGE requires queries in the form:

SELECT * FROM ag_catalog.cypher('graph_name', $$ CYPHER $$, $1) AS (v agtype)

Where $1 is a JSON-encoded map of parameters.

Summary

Functions

Builds a parameterized Cypher query wrapped for AGE execution.

Builds a parameterized Cypher query with custom return type columns.

Builds a static Cypher query (no parameters).

Builds a static Cypher query with custom return type columns.

build/4 wrapped so a non-JSON-encodable param value fails closed as {:error, :params_not_json_encodable} instead of raising: Jason.EncodeError embeds the raw bytes in its message, and Protocol.UndefinedError (a struct with no Jason.Encoder impl nested in a param) inspects the value into its message. This is the ONE home for that classifier — every executing caller (AshAge.DataLayer.build_and_query, AshAge.Changes.EdgeCypher.safe_build, AshAge.cypher/5, the traverse path) routes through it, so the redaction logic cannot drift between copies. Identifier/$$-breakout ArgumentErrors propagate unchanged: they are value-free by design and must stay loud.

Functions

build(graph, cypher, params)

@spec build(atom() | String.t(), String.t(), map()) :: {String.t(), list()}

Builds a parameterized Cypher query wrapped for AGE execution.

Returns {sql_string, [json_params]} suitable for Ecto.Adapters.SQL.query/3.

build(graph, cypher, params, return_types)

@spec build(atom() | String.t(), String.t(), map(), keyword()) :: {String.t(), list()}

Builds a parameterized Cypher query with custom return type columns.

return_types is a keyword list like [{:v, :agtype}, {:e, :agtype}].

build_static(graph, cypher)

@spec build_static(atom() | String.t(), String.t()) :: {String.t(), list()}

Builds a static Cypher query (no parameters).

Omits the params argument entirely — AGE rejects NULL as the third argument.

build_static(graph, cypher, return_types)

@spec build_static(atom() | String.t(), String.t(), keyword()) :: {String.t(), list()}

Builds a static Cypher query with custom return type columns.

safe_build(graph, cypher, params, return_types)

@spec safe_build(atom() | String.t(), String.t(), map(), keyword()) ::
  {:ok, {String.t(), list()}} | {:error, :params_not_json_encodable}

build/4 wrapped so a non-JSON-encodable param value fails closed as {:error, :params_not_json_encodable} instead of raising: Jason.EncodeError embeds the raw bytes in its message, and Protocol.UndefinedError (a struct with no Jason.Encoder impl nested in a param) inspects the value into its message. This is the ONE home for that classifier — every executing caller (AshAge.DataLayer.build_and_query, AshAge.Changes.EdgeCypher.safe_build, AshAge.cypher/5, the traverse path) routes through it, so the redaction logic cannot drift between copies. Identifier/$$-breakout ArgumentErrors propagate unchanged: they are value-free by design and must stay loud.