ArcadeDB user-defined functions — tenant-blind DEFINE FUNCTION / DELETE FUNCTION DDL,
parallel to Arcadic.FullText/Arcadic.Geo.
A function name is a dotted library.fn reference validated per segment
(String.split(name, "."), each segment through Arcadic.Identifier — a bare
Identifier.validate is wrong, it rejects .; a degenerate lib..fn yields an empty
segment that fails closed). The body is embedded as a "..." DDL literal and admitted only
through an internal positive-allowlist guard — the sole breakout byte ", the backslash,
and control/line bytes are rejected value-free before any wire call. ArcadeDB's "..."
body literal has no escape (\", doubled "", single-quote delimiter, and newlines all
parse-error), so the single-line/single-quoted-body limit is a substrate constraint, not a
narrowing — ArcadeDB's own e2e tests use only single-line, single-quoted-JS bodies.
Calling a defined function
There is no call wrapper here (a call wrapper is a query template — a charter non-goal).
Invoke a defined function inside an ordinary Arcadic.query/4 via the backtick idiom:
Arcadic.query(conn, "SELECT `math.sum`(:a, :b) AS total", %{"a" => 1, "b" => 2},
language: "sql")The library/function name is interpolated (behind the per-segment allowlist); the arguments
ride the params map, never the statement.
Summary
Functions
Defines a function name (a dotted library.fn) with a body literal and opts
Defines a function, raising on error.
Deletes a function name (a dotted library.fn); idempotent server-side once the library exists (deleting from a never-defined library errors). Value-free on a bad name.
Deletes a function, raising on error.
Functions
@spec define(Arcadic.Conn.t(), String.t(), String.t(), keyword()) :: :ok | {:error, atom() | Exception.t()}
Defines a function name (a dotted library.fn) with a body literal and opts:
:params— a list of parameter-name atoms/strings, eachIdentifier-validated (default[]).:language—:js(default) |:sql|:cypher.
A single trailing opts keyword list (like every sibling DDL helper), so there is no
positional-argument ambiguity:
define(conn, "math.sum", "return a + b", params: [:a, :b], language: :sql)
define(conn, "lib.fn", "return 1") # no params, js
define(conn, "lib.fn", "return 1", language: :sql) # opts, no paramsEmits DEFINE FUNCTION lib.fn "body" [PARAMETERS [a, b]] LANGUAGE <lang>. Value-free on a bad
name (:invalid_identifier), a bad param (:invalid_identifier), an unencodable body
(:unencodable_body), or an unknown language (:invalid_language) — none echo the offending
value. A non-binary body is a caller-contract violation and raises ArgumentError value-free.
@spec define!(Arcadic.Conn.t(), String.t(), String.t(), keyword()) :: :ok
Defines a function, raising on error.
@spec delete(Arcadic.Conn.t(), String.t()) :: :ok | {:error, atom() | Exception.t()}
Deletes a function name (a dotted library.fn); idempotent server-side once the library exists (deleting from a never-defined library errors). Value-free on a bad name.
@spec delete!(Arcadic.Conn.t(), String.t()) :: :ok
Deletes a function, raising on error.