# `TerminusDB.WOQL`
[🔗](https://github.com/thanos/terminusdb-client-elixir/blob/v0.3.3/lib/terminus_db/woql.ex#L1)

A functional builder DSL for WOQL (Web Object Query Language).

WOQL is TerminusDB's Datalog-based query language. This module provides a
comprehensive set of ~100 composable functions that build a `TerminusDB.WOQL.Query`
struct, which can be serialized to the JSON-LD wire format via `to_jsonld/1`
and executed via `TerminusDB.WOQL.execute/3`.

This is WOQL DSL v0.2 (ADR-0008) extended in v0.3.2 with temporal/Allen,
CSV/IO, range queries, and an RDF list library.

## Design

The DSL is purely functional (no macros). Each function returns a
`%WOQL.Query{}` struct and composes by nesting, mirroring the recommended
functional WOQL style. Variables are plain strings using the `v:Name`
convention.

The JSON-LD encoder uses four value-wrapper types matching the Python/JS
clients: `NodeValue` (nodes/IRIs), `Value` (generic values), `DataValue`
(literal data), and `ArithmeticValue` (arithmetic operands). Use `iri/1` to
explicitly mark a string as an IRI in triple object position (string objects
default to `xsd:string` literals).

## Supported vocabulary (v0.2)

### Logical combinators

| Function | WOQL JSON-LD type |
| --- | --- |
| `and_/1` | `And` |
| `or_/1` | `Or` |
| `not_/1` | `Not` |
| `opt/1` (alias `optional/1`) | `Optional` |
| `once/1` | `Once` |
| `immediately/1` | `Immediately` |

### Query modifiers

| Function | WOQL JSON-LD type |
| --- | --- |
| `select/2` | `Select` |
| `distinct/2` | `Distinct` |
| `limit/2` | `Limit` |
| `start/2` | `Start` |
| `order_by/2` | `OrderBy` |
| `group_by/4` | `GroupBy` |
| `count/2` | `Count` |
| `collect/3` | `Collect` |
| `star/0`, `all/0` | `Triple` (shortcut) |

### Graph patterns

| Function | WOQL JSON-LD type |
| --- | --- |
| `triple/3` | `Triple` |
| `quad/4` | `Triple` + `graph` |
| `added_triple/3`, `added_quad/4` | `AddedTriple` |
| `removed_triple/3`, `removed_quad/4` | `DeletedTriple` |
| `add_triple/3`, `add_quad/4` | `AddTriple` |
| `delete_triple/3`, `delete_quad/4` | `DeleteTriple` |
| `update_triple/3`, `update_quad/4` | `And` (macro) |

### Comparison

| Function | WOQL JSON-LD type |
| --- | --- |
| `eq/2` | `Equals` |
| `less/2` | `Less` |
| `greater/2` | `Greater` |
| `gte/2` | `Gte` |
| `lte/2` | `Lte` |
| `like/3` | `Like` |

### Schema ops

| Function | WOQL JSON-LD type |
| --- | --- |
| `type_of/2` | `TypeOf` |
| `isa/2` | `IsA` |
| `sub/2` (alias `subsumption/2`) | `Subsumption` |
| `cast/3` (alias `typecast/3`) | `Typecast` |

### Arithmetic

| Function | WOQL JSON-LD type |
| --- | --- |
| `eval/2` | `Eval` |
| `plus/1`, `minus/1`, `times/1`, `divide/1` | `Plus`/`Minus`/`Times`/`Divide` |
| `div/1` | `Div` |
| `exp/2` | `Exp` |
| `floor/1` | `Floor` |
| `sum/2` | `Sum` |

### String ops

| Function | WOQL JSON-LD type |
| --- | --- |
| `concat/2` (alias `concatenate/2`) | `Concatenate` |
| `join/3` | `Join` |
| `substr/5` (alias `substring/5`) | `Substring` |
| `trim/2` | `Trim` |
| `upper/2` | `Upper` |
| `lower/2` | `Lower` |
| `pad/4` | `Pad` |
| `split/3` | `Split` |
| `length/2` | `Length` |
| `regexp/3` | `Regexp` |

### List / Set / Dict ops

| Function | WOQL JSON-LD type |
| --- | --- |
| `dot/3` | `Dot` |
| `member/2` | `Member` |
| `slice/4` | `Slice` |
| `set_difference/3` | `SetDifference` |
| `set_intersection/3` | `SetIntersection` |
| `set_union/3` | `SetUnion` |
| `set_member/2` | `SetMember` |
| `list_to_set/2` | `ListToSet` |

### Path / navigation

| Function | WOQL JSON-LD type |
| --- | --- |
| `path/3`, `path/4` | `Path` |

Path patterns accept both string patterns (`path("v:S", "friend*", "v:O")`)
and structured builders via `TerminusDB.WOQL.Path` (`path_star/1`,
`path_plus/1`, `path_times/3`, `path_seq/1`, `path_or/1`, `path_inverse/1`,
`path_pred/1`, `path_any/0`).

### ID generation

| Function | WOQL JSON-LD type |
| --- | --- |
| `unique/3` | `HashKey` |
| `idgen/3` (alias `idgenerator/3`) | `LexicalKey` |
| `idgen_random/2` (alias `random_idgen/2`) | `RandomKey` |

### Documents

| Function | WOQL JSON-LD type |
| --- | --- |
| `read_document/2` | `ReadDocument` |
| `insert_document/2` | `InsertDocument` |
| `update_document/2` | `UpdateDocument` |
| `delete_document/1` | `DeleteDocument` |

### Graph context

| Function | WOQL JSON-LD type |
| --- | --- |
| `using/2` | `Using` |
| `from/2` | `From` |
| `into/2` | `Into` |
| `comment/2` | `Comment` |

### Graph meta

| Function | WOQL JSON-LD type |
| --- | --- |
| `size/2` | `Size` |
| `triple_count/2` | `TripleCount` |

### Range queries

| Function | WOQL JSON-LD type |
| --- | --- |
| `triple_slice/5`, `quad_slice/6` | `TripleSlice` |
| `triple_slice_rev/5`, `quad_slice_rev/6` | `TripleSliceRev` |
| `triple_next/4`, `quad_next/5` | `TripleNext` |
| `triple_previous/4`, `quad_previous/5` | `TriplePrevious` |

### Temporal / Allen interval algebra

| Function | WOQL JSON-LD type |
| --- | --- |
| `interval/3` | `Interval` |
| `interval_start_duration/3` | `IntervalStartDuration` |
| `interval_duration_end/3` | `IntervalDurationEnd` |
| `interval_relation/5` | `IntervalRelation` |
| `interval_relation_typed/3` | `IntervalRelationTyped` |
| `date_duration/3` | `DateDuration` |
| `day_after/2` | `DayAfter` |
| `day_before/2` | `DayBefore` |
| `weekday/2` | `Weekday` |
| `weekday_sunday_start/2` | `WeekdaySundayStart` |
| `iso_week/3` | `IsoWeek` |
| `month_start_date/2` | `MonthStartDate` |
| `month_end_date/2` | `MonthEndDate` |
| `month_start_dates/3` | `MonthStartDates` |
| `month_end_dates/3` | `MonthEndDates` |
| `in_range/3` | `InRange` |
| `sequence/5` | `Sequence` |
| `range_min/2` | `RangeMin` |
| `range_max/2` | `RangeMax` |

### CSV / IO

| Function | WOQL JSON-LD type |
| --- | --- |
| `get/2` | `Get` |
| `put/3` | `Put` |
| `woql_as/1` | `Column`/`Indicator` (helper) |
| `file/2` | `QueryResource` |
| `remote/2` | `QueryResource` |
| `post/2` | `QueryResource` |

### RDF list library

See `TerminusDB.WOQL.RDFList` for 17 RDF list manipulation functions.

### Literal / value helpers

| Function | Description |
| --- | --- |
| `var/1` | Wraps a name as `"v:Name"` |
| `iri/1` | Wraps a string as a `NodeValue` IRI |
| `string/1` | Wraps as `xsd:string` literal |
| `boolean/1` | Wraps as `xsd:boolean` literal |
| `datetime/1` | Wraps as `xsd:dateTime` literal |
| `date/1` | Wraps as `xsd:date` literal |
| `literal/2` | Generic typed literal |
| `true_/0` | `True` constant |

## Quick start

    import TerminusDB.WOQL

    query =
      and_([
        triple("v:Person", "rdf:type", iri("@schema:Person")),
        triple("v:Person", "name", "v:Name")
      ])

    jsonld = TerminusDB.WOQL.to_jsonld(query)

    # Execute against a database
    config = TerminusDB.Config.new(endpoint: "http://localhost:6363")
    config = TerminusDB.Config.with_database(config, "mydb")
    {:ok, result} = TerminusDB.WOQL.execute(config, query)

# `t`

```elixir
@type t() :: %TerminusDB.WOQL{args: [term()], op: atom()}
```

# `value`

```elixir
@type value() :: String.t() | woql_var() | number() | boolean() | map() | [value()]
```

# `woql_node`

```elixir
@type woql_node() :: String.t() | woql_var()
```

# `woql_var`

```elixir
@type woql_var() :: String.t()
```

# `add_quad`

```elixir
@spec add_quad(woql_node(), woql_node(), value(), String.t()) :: t()
```

Builds an `AddTriple` with a graph — adds quads.

## Examples

    iex> q = TerminusDB.WOQL.add_quad("v:S", "name", "Alice", "instance")
    iex> q.op
    :add_quad

# `add_triple`

```elixir
@spec add_triple(woql_node(), woql_node(), value()) :: t()
```

Builds an `AddTriple` — adds triples matching `[S, P, O]`.

## Examples

    iex> q = TerminusDB.WOQL.add_triple("v:S", "name", "Alice")
    iex> q.op
    :add_triple

# `added_quad`

```elixir
@spec added_quad(woql_node(), woql_node(), value(), String.t()) :: t()
```

Builds an `AddedTriple` with a graph — a quad added in the current commit.

## Examples

    iex> q = TerminusDB.WOQL.added_quad("v:S", "name", "v:N", "instance")
    iex> q.op
    :added_quad

# `added_triple`

```elixir
@spec added_triple(woql_node(), woql_node(), value()) :: t()
```

Builds an `AddedTriple` — a triple added in the current commit.

## Examples

    iex> q = TerminusDB.WOQL.added_triple("v:S", "name", "v:N")
    iex> q.op
    :added_triple

# `all`

```elixir
@spec all() :: t()
```

Alias for `star/0`.

# `and_`

```elixir
@spec and_([t()]) :: t()
```

Builds an `And` conjunction of sub-queries.

## Examples

    iex> q = TerminusDB.WOQL.and_([
    ...>   TerminusDB.WOQL.triple("v:S", "rdf:type", "v:T"),
    ...>   TerminusDB.WOQL.eq("v:T", "Person")
    ...> ])
    iex> q.op
    :and

# `boolean`

```elixir
@spec boolean(boolean()) :: map()
```

Wraps a boolean as an `xsd:boolean` literal dict.

## Examples

    iex> TerminusDB.WOQL.boolean(true)
    %{"@type" => "xsd:boolean", "@value" => true}

# `cast`

```elixir
@spec cast(value(), value(), value()) :: t()
```

Builds a `Typecast` — casts `value` to `type`, binding to `result`.

## Examples

    iex> q = TerminusDB.WOQL.cast("v:Val", "xsd:integer", "v:Result")
    iex> q.op
    :cast

# `collect`

```elixir
@spec collect(value(), value(), t()) :: t()
```

Builds a `Collect` — collects all solutions into a list.

## Examples

    iex> q = TerminusDB.WOQL.collect("v:Template", "v:Into",
    ...>   TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :collect

# `comment`

```elixir
@spec comment(String.t(), t()) :: t()
```

Builds a `Comment` — attaches a text comment to a sub-query.

## Examples

    iex> q = TerminusDB.WOQL.comment("find friends", TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :comment

# `concat`

```elixir
@spec concat([value()], value()) :: t()
```

Builds a `Concatenate` — concatenates a list of strings/vars into `result`.

## Examples

    iex> q = TerminusDB.WOQL.concat(["v:First", " ", "v:Last"], "v:Full")
    iex> q.op
    :concat

# `concatenate`

```elixir
@spec concatenate([value()], value()) :: t()
```

Alias for `concat/2`.

# `count`

```elixir
@spec count(woql_var(), t()) :: t()
```

Builds a `Count` — counts solutions of the sub-query and binds to `countvar`.

## Examples

    iex> q = TerminusDB.WOQL.count("v:N", TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :count

# `date`

```elixir
@spec date(Date.t() | String.t()) :: map()
```

Wraps a `Date` or ISO 8601 string as an `xsd:date` literal dict.

## Examples

    iex> TerminusDB.WOQL.date("2026-01-15")
    %{"@type" => "xsd:date", "@value" => "2026-01-15"}

# `date_duration`

```elixir
@spec date_duration(value(), value(), value()) :: t()
```

Builds a `DateDuration` — tri-directional duration arithmetic for
dates/dateTimes (end-of-month preserving).

## Examples

    iex> q = TerminusDB.WOQL.date_duration("v:Start", "v:End", "v:Dur")
    iex> q.op
    :date_duration

# `datetime`

```elixir
@spec datetime(DateTime.t() | NaiveDateTime.t() | String.t()) :: map()
```

Wraps a `DateTime`, `NaiveDateTime`, or ISO 8601 string as an
`xsd:dateTime` literal dict.

## Examples

    iex> TerminusDB.WOQL.datetime("2026-01-15T10:30:00Z")
    %{"@type" => "xsd:dateTime", "@value" => "2026-01-15T10:30:00Z"}

# `day_after`

```elixir
@spec day_after(value(), value()) :: t()
```

Builds a `DayAfter` — computes the calendar day after the given date
(bidirectional).

## Examples

    iex> q = TerminusDB.WOQL.day_after("v:Date", "v:Next")
    iex> q.op
    :day_after

# `day_before`

```elixir
@spec day_before(value(), value()) :: t()
```

Builds a `DayBefore` — computes the calendar day before the given date
(bidirectional).

## Examples

    iex> q = TerminusDB.WOQL.day_before("v:Date", "v:Prev")
    iex> q.op
    :day_before

# `delete_document`

```elixir
@spec delete_document(woql_node()) :: t()
```

Builds a `DeleteDocument` — delete a document by IRI.

## Examples

    iex> q = TerminusDB.WOQL.delete_document("Person/Alice")
    iex> q.op
    :delete_document

# `delete_quad`

```elixir
@spec delete_quad(woql_node(), woql_node(), value(), String.t()) :: t()
```

Builds a `DeleteTriple` with a graph — deletes quads.

## Examples

    iex> q = TerminusDB.WOQL.delete_quad("v:S", "name", "v:O", "instance")
    iex> q.op
    :delete_quad

# `delete_triple`

```elixir
@spec delete_triple(woql_node(), woql_node(), value()) :: t()
```

Builds a `DeleteTriple` — deletes triples matching `[S, P, O]`.

## Examples

    iex> q = TerminusDB.WOQL.delete_triple("v:S", "name", "v:O")
    iex> q.op
    :delete_triple

# `distinct`

```elixir
@spec distinct([woql_var()], t()) :: t()
```

Builds a `Distinct` — returns distinct solutions for the given variables.

## Examples

    iex> q = TerminusDB.WOQL.distinct(["v:Name"], TerminusDB.WOQL.triple("v:P", "name", "v:Name"))
    iex> q.op
    :distinct

# `div`

```elixir
@spec div([value() | t()]) :: t()
```

Builds a `Div` — integer division of a list of arithmetic values.

## Examples

    iex> q = TerminusDB.WOQL.div(["v:X", 5])
    iex> q.op
    :div

# `divide`

```elixir
@spec divide([value() | t()]) :: t()
```

Builds a `Divide` — divides a list of arithmetic values left-to-right.

## Examples

    iex> q = TerminusDB.WOQL.divide(["v:X", 5])
    iex> q.op
    :divide

# `dot`

```elixir
@spec dot(value(), value(), value()) :: t()
```

Builds a `Dot` — accesses a dictionary field or list element.

## Examples

    iex> q = TerminusDB.WOQL.dot("v:Doc", "field", "v:Value")
    iex> q.op
    :dot

# `eq`

```elixir
@spec eq(value(), value()) :: t()
```

Builds an `Equals` unification: left equals right.

## Examples

    iex> q = TerminusDB.WOQL.eq("v:Name", "Alice")
    iex> q.op
    :eq

# `eval`

```elixir
@spec eval(t(), value()) :: t()
```

Builds an `Eval` — evaluates an arithmetic expression and binds to `result`.

The `expression` is typically a nested arithmetic query such as `plus/1`,
`minus/1`, `times/1`, etc.

## Examples

    iex> q = TerminusDB.WOQL.eval(TerminusDB.WOQL.plus(["v:X", 5]), "v:Result")
    iex> q.op
    :eval

# `execute`

```elixir
@spec execute(TerminusDB.Config.t(), t(), keyword()) ::
  {:ok, map()} | {:error, TerminusDB.Error.t()}
```

Executes a WOQL query against the database scoped in `config`.

Returns `{:ok, result}` where `result` is a map containing `bindings` (a list
of maps, one per solution), or `{:error, TerminusDB.Error.t()}`.

## Options

- `:author` - commit author (for write queries).
- `:message` - commit message (for write queries).
- `:all_witnesses` - check for all errors (default `false`).
- `:organization` - overrides `config.organization`.
- `:repo` - overrides `config.repo`.
- `:branch` - overrides `config.branch`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req ->
    ...>     {req, Req.Response.new(status: 200, body: %{"bindings" => [%{"Name" => "Alice"}]})}
    ...>   end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> q = TerminusDB.WOQL.select(["v:Name"],
    ...>   TerminusDB.WOQL.and_([TerminusDB.WOQL.triple("v:P", "name", "v:Name")])
    ...> )
    iex> {:ok, result} = TerminusDB.WOQL.execute(config, q)
    iex> result["bindings"]
    [%{"Name" => "Alice"}]

# `execute!`

```elixir
@spec execute!(TerminusDB.Config.t(), t(), keyword()) :: map()
```

Executes a WOQL query, or raises `TerminusDB.Error`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"bindings" => []})} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> q = TerminusDB.WOQL.triple("v:S", "p", "v:O")
    iex> TerminusDB.WOQL.execute!(config, q)
    %{"bindings" => []}

# `execute_stream`

```elixir
@spec execute_stream(TerminusDB.Config.t(), t(), keyword()) ::
  {:ok, Enumerable.t()} | {:error, TerminusDB.Error.t()}
```

Executes a WOQL query and returns a lazy `Stream` of binding maps.

The stream uses the PrefaceRecord/Binding/PostscriptRecord protocol for
incremental delivery. Each element is a `%{"@type" => "Binding", ...}` map.

## Options

Same as `execute/3`.

## Examples

    iex> config = TerminusDB.Config.new(
    ...>   endpoint: "http://localhost:6363",
    ...>   adapter: fn req -> {req, Req.Response.new(status: 200, body: [%{"@type" => "PrefaceRecord", "names" => ["Name"]}, %{"@type" => "Binding", "Name" => "Alice"}, %{"@type" => "PostscriptRecord"}])} end
    ...> ) |> TerminusDB.Config.with_database("mydb")
    iex> q = TerminusDB.WOQL.select(["v:Name"], TerminusDB.WOQL.triple("v:P", "name", "v:Name"))
    iex> {:ok, stream} = TerminusDB.WOQL.execute_stream(config, q)
    iex> Enum.to_list(stream)
    [%{"@type" => "Binding", "Name" => "Alice"}]

# `exp`

```elixir
@spec exp(value() | t(), value() | t()) :: t()
```

Builds an `Exp` — `base` raised to the power of `exponent`.

## Examples

    iex> q = TerminusDB.WOQL.exp("v:X", 2)
    iex> q.op
    :exp

# `file`

```elixir
@spec file(
  String.t(),
  keyword()
) :: t()
```

Builds a `QueryResource` for a file source (CSV format by default).

## Examples

    iex> q = TerminusDB.WOQL.file("data.csv")
    iex> q.op
    :file

# `floor`

```elixir
@spec floor(value() | t()) :: t()
```

Builds a `Floor` — greatest integer ≤ `value`.

## Examples

    iex> q = TerminusDB.WOQL.floor("v:X")
    iex> q.op
    :floor

# `from`

```elixir
@spec from(String.t(), t()) :: t()
```

Builds a `From` — sets the default graph for the enclosed query.

## Examples

    iex> q = TerminusDB.WOQL.from("instance", TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :from

# `from_jsonld`

```elixir
@spec from_jsonld(map()) :: t()
```

Deserializes a JSON-LD WOQL query back into a `WOQL.Query` struct.

## Examples

    iex> jsonld = %{"@type" => "Triple", "subject" => %{"@type" => "NodeValue", "variable" => "S"}, "predicate" => %{"@type" => "NodeValue", "node" => "name"}, "object" => %{"@type" => "Value", "variable" => "N"}}
    iex> q = TerminusDB.WOQL.from_jsonld(jsonld)
    iex> q.op
    :triple

# `get`

```elixir
@spec get([map()], t()) :: t()
```

Builds a `Get` — reads a CSV/columns resource.

`as_vars` is a list of `Column` objects built by `woql_as/1`.
`query_resource` is built by `file/2`, `remote/2`, or `post/2`.

## Examples

    iex> q = TerminusDB.WOQL.get(TerminusDB.WOQL.woql_as([{"name", "v:Name"}]), TerminusDB.WOQL.file("data.csv"))
    iex> q.op
    :get

# `greater`

```elixir
@spec greater(value(), value()) :: t()
```

Builds a `Greater` comparison: `left > right`.

## Examples

    iex> q = TerminusDB.WOQL.greater("v:Age", 30)
    iex> q.op
    :greater

# `group_by`

```elixir
@spec group_by([woql_var()], value(), value(), t()) :: t()
```

Builds a `GroupBy` — groups sub-query results by `vars` using `template`,
binding into `grouped`.

## Examples

    iex> q = TerminusDB.WOQL.group_by(["v:Type"], "v:Template", "v:Grouped",
    ...>   TerminusDB.WOQL.triple("v:S", "rdf:type", "v:Type"))
    iex> q.op
    :group_by

# `gte`

```elixir
@spec gte(value(), value()) :: t()
```

Builds a `Gte` comparison: `left >= right`.

## Examples

    iex> q = TerminusDB.WOQL.gte("v:Age", 30)
    iex> q.op
    :gte

# `idgen`

```elixir
@spec idgen(String.t(), [value()], woql_var()) :: t()
```

Builds a `LexicalKey` — lexical (deterministic, non-hash) ID.

## Examples

    iex> q = TerminusDB.WOQL.idgen("Person/", ["v:Name"], "v:ID")
    iex> q.op
    :idgen

# `idgen_random`

```elixir
@spec idgen_random(String.t(), woql_var()) :: t()
```

Builds a `RandomKey` — cryptographically-secure random ID.

## Examples

    iex> q = TerminusDB.WOQL.idgen_random("Person/", "v:ID")
    iex> q.op
    :idgen_random

# `idgenerator`

```elixir
@spec idgenerator(String.t(), [value()], woql_var()) :: t()
```

Alias for `idgen/3`.

# `immediately`

```elixir
@spec immediately(t()) :: t()
```

Builds an `Immediately` — run side-effects without backtracking.

## Examples

    iex> q = TerminusDB.WOQL.immediately(TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :immediately

# `in_range`

```elixir
@spec in_range(value(), value(), value()) :: t()
```

Builds an `InRange` — tests whether value falls within half-open
range [start, end).

## Examples

    iex> q = TerminusDB.WOQL.in_range("v:Val", 10, 100)
    iex> q.op
    :in_range

# `insert_document`

```elixir
@spec insert_document(value(), woql_node() | nil) :: t()
```

Builds an `InsertDocument` — inserts a document.

`identifier` is a variable (e.g. `"v:Id"`) that will be bound to the
inserted document's IRI. TerminusDB 12 requires it for well-formed
`InsertDocument` JSON-LD.

## Examples

    iex> q = TerminusDB.WOQL.insert_document("v:Doc")
    iex> q.op
    :insert_document

    iex> q = TerminusDB.WOQL.insert_document(%{"@type" => "Person"}, "v:Id")
    iex> q.op
    :insert_document

# `interval`

```elixir
@spec interval(value(), value(), value()) :: t()
```

Builds an `Interval` — constructs/deconstructs a half-open
`xdd:dateTimeInterval` [start, end).

## Examples

    iex> q = TerminusDB.WOQL.interval("v:Start", "v:End", "v:I")
    iex> q.op
    :interval

# `interval_duration_end`

```elixir
@spec interval_duration_end(value(), value(), value()) :: t()
```

Builds an `IntervalDurationEnd` — relates interval to end endpoint
and precise `xsd:duration`.

## Examples

    iex> q = TerminusDB.WOQL.interval_duration_end("v:Dur", "v:End", "v:I")
    iex> q.op
    :interval_duration_end

# `interval_relation`

```elixir
@spec interval_relation(value(), value(), value(), value(), value()) :: t()
```

Builds an `IntervalRelation` — Allen's Interval Algebra: classifies
the relationship between two half-open intervals.

## Examples

    iex> q = TerminusDB.WOQL.interval_relation("v:Rel", "v:XS", "v:XE", "v:YS", "v:YE")
    iex> q.op
    :interval_relation

# `interval_relation_typed`

```elixir
@spec interval_relation_typed(value(), value(), value()) :: t()
```

Builds an `IntervalRelationTyped` — Allen's Interval Algebra on
`xdd:dateTimeInterval` values.

## Examples

    iex> q = TerminusDB.WOQL.interval_relation_typed("v:Rel", "v:X", "v:Y")
    iex> q.op
    :interval_relation_typed

# `interval_start_duration`

```elixir
@spec interval_start_duration(value(), value(), value()) :: t()
```

Builds an `IntervalStartDuration` — relates interval to start endpoint
and precise `xsd:duration`.

## Examples

    iex> q = TerminusDB.WOQL.interval_start_duration("v:Start", "v:Dur", "v:I")
    iex> q.op
    :interval_start_duration

# `into`

```elixir
@spec into(String.t(), t()) :: t()
```

Builds an `Into` — sets the output graph for writing.

## Examples

    iex> q = TerminusDB.WOQL.into("schema", TerminusDB.WOQL.add_triple("v:S", "p", "v:O"))
    iex> q.op
    :into

# `iri`

```elixir
@spec iri(String.t()) :: map()
```

Wraps a string as a `NodeValue` IRI — use for triple objects that should be
treated as IRIs rather than string literals.

## Examples

    iex> TerminusDB.WOQL.iri("@schema:Person")
    %{"@type" => "NodeValue", "node" => "@schema:Person"}

# `isa`

```elixir
@spec isa(woql_node(), woql_node()) :: t()
```

Builds an `IsA` — true if `element` is a member of `of_type`.

## Examples

    iex> q = TerminusDB.WOQL.isa("v:X", WOQL.iri("@schema:Person"))
    iex> q.op
    :isa

# `iso_week`

```elixir
@spec iso_week(value(), value(), value()) :: t()
```

Builds an `IsoWeek` — computes ISO 8601 week-numbering year and
week number.

## Examples

    iex> q = TerminusDB.WOQL.iso_week("v:Date", "v:Year", "v:Week")
    iex> q.op
    :iso_week

# `join`

```elixir
@spec join(value(), value(), value()) :: t()
```

Builds a `Join` — joins a list into a string with `glue`.

## Examples

    iex> q = TerminusDB.WOQL.join("v:List", ", ", "v:Result")
    iex> q.op
    :join

# `length`

```elixir
@spec length(value(), value()) :: t()
```

Builds a `Length` — binds the length of a list.

## Examples

    iex> q = TerminusDB.WOQL.length("v:List", "v:Len")
    iex> q.op
    :length

# `less`

```elixir
@spec less(value(), value()) :: t()
```

Builds a `Less` comparison: `left < right`.

## Examples

    iex> q = TerminusDB.WOQL.less("v:Age", 30)
    iex> q.op
    :less

# `like`

```elixir
@spec like(value(), value(), value()) :: t()
```

Builds a `Like` — string similarity with edit-distance `dist`.

## Examples

    iex> q = TerminusDB.WOQL.like("v:Name", "Alice", 2)
    iex> q.op
    :like

# `limit`

```elixir
@spec limit(non_neg_integer(), t()) :: t()
```

Builds a `Limit` — maximum number of results.

## Examples

    iex> q = TerminusDB.WOQL.limit(10, TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :limit

# `list_to_set`

```elixir
@spec list_to_set(value(), value()) :: t()
```

Builds a `ListToSet` — converts a list to a set.

## Examples

    iex> q = TerminusDB.WOQL.list_to_set("v:List", "v:Set")
    iex> q.op
    :list_to_set

# `literal`

```elixir
@spec literal(term(), String.t()) :: map()
```

Wraps a value as a typed literal dict. The type is prefixed with `xsd:` if it
does not already contain a colon.

## Examples

    iex> TerminusDB.WOQL.literal("42", "integer")
    %{"@type" => "xsd:integer", "@value" => "42"}

# `lower`

```elixir
@spec lower(value(), value()) :: t()
```

Builds a `Lower` — converts to lowercase.

## Examples

    iex> q = TerminusDB.WOQL.lower("v:Input", "v:Result")
    iex> q.op
    :lower

# `lte`

```elixir
@spec lte(value(), value()) :: t()
```

Builds an `Lte` comparison: `left <= right`.

## Examples

    iex> q = TerminusDB.WOQL.lte("v:Age", 30)
    iex> q.op
    :lte

# `member`

```elixir
@spec member(value(), value()) :: t()
```

Builds a `Member` — iterates members of a list.

## Examples

    iex> q = TerminusDB.WOQL.member("v:Item", "v:List")
    iex> q.op
    :member

# `minus`

```elixir
@spec minus([value() | t()]) :: t()
```

Builds a `Minus` — subtracts a list of arithmetic values left-to-right.

## Examples

    iex> q = TerminusDB.WOQL.minus(["v:X", 5])
    iex> q.op
    :minus

# `month_end_date`

```elixir
@spec month_end_date(value(), value()) :: t()
```

Builds a `MonthEndDate` — last day of the month for a given
`xsd:gYearMonth` (handles leap years).

## Examples

    iex> q = TerminusDB.WOQL.month_end_date("v:YM", "v:Date")
    iex> q.op
    :month_end_date

# `month_end_dates`

```elixir
@spec month_end_dates(value(), value(), value()) :: t()
```

Builds a `MonthEndDates` — generator: every last-of-month date
in [start, end).

## Examples

    iex> q = TerminusDB.WOQL.month_end_dates("v:Date", "v:Start", "v:End")
    iex> q.op
    :month_end_dates

# `month_start_date`

```elixir
@spec month_start_date(value(), value()) :: t()
```

Builds a `MonthStartDate` — first day of the month for a given
`xsd:gYearMonth`.

## Examples

    iex> q = TerminusDB.WOQL.month_start_date("v:YM", "v:Date")
    iex> q.op
    :month_start_date

# `month_start_dates`

```elixir
@spec month_start_dates(value(), value(), value()) :: t()
```

Builds a `MonthStartDates` — generator: every first-of-month date
in [start, end).

## Examples

    iex> q = TerminusDB.WOQL.month_start_dates("v:Date", "v:Start", "v:End")
    iex> q.op
    :month_start_dates

# `not_`

```elixir
@spec not_(t()) :: t()
```

Builds a `Not` negation of a sub-query.

## Examples

    iex> q = TerminusDB.WOQL.not_(TerminusDB.WOQL.eq("v:N", "Alice"))
    iex> q.op
    :not

# `once`

```elixir
@spec once(t()) :: t()
```

Builds a `Once` — obtain only one result from the sub-query.

## Examples

    iex> q = TerminusDB.WOQL.once(TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :once

# `opt`

```elixir
@spec opt(t()) :: t()
```

Builds an `Optional` wrapper — the sub-query is allowed to fail without
invalidating the enclosing query.

## Examples

    iex> q = TerminusDB.WOQL.opt(TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :opt

# `optional`

```elixir
@spec optional(t()) :: t()
```

Alias for `opt/1`.

# `or_`

```elixir
@spec or_([t()]) :: t()
```

Builds an `Or` disjunction of sub-queries.

## Examples

    iex> q = TerminusDB.WOQL.or_([
    ...>   TerminusDB.WOQL.eq("v:Name", "Alice"),
    ...>   TerminusDB.WOQL.eq("v:Name", "Bob")
    ...> ])
    iex> q.op
    :or

# `order_by`

```elixir
@spec order_by([{String.t(), :asc | :desc}] | keyword(), t()) :: t()
```

Builds an `OrderBy` — orders results by the given variables.

Accepts both tuple-list and keyword-list forms:

    # Tuple list
    TerminusDB.WOQL.order_by([{"v:Time", :asc}, {"v:Name", :desc}], query)

    # Keyword list
    TerminusDB.WOQL.order_by([time: :asc, name: :desc], query)

## Examples

    iex> q = TerminusDB.WOQL.order_by([{"v:Name", :asc}], TerminusDB.WOQL.triple("v:S", "name", "v:Name"))
    iex> q.op
    :order_by

    iex> q2 = TerminusDB.WOQL.order_by([name: :desc], TerminusDB.WOQL.triple("v:S", "name", "v:Name"))
    iex> q2.op
    :order_by

# `pad`

```elixir
@spec pad(value(), value(), value(), value()) :: t()
```

Builds a `Pad` — pads string to `length` with `pad`.

## Examples

    iex> q = TerminusDB.WOQL.pad("v:Input", "0", 10, "v:Result")
    iex> q.op
    :pad

# `path`

```elixir
@spec path(woql_node(), String.t() | tuple(), value()) :: t()
```

Builds a `Path` query — traverses the graph from `subject` to `object`
following the given `pattern`.

The pattern can be either a string (compiled via `TerminusDB.WOQL.Path`) or
an AST node built via the structured builders (`path_star/1`, `path_plus/1`,
etc.).

## String patterns

    # Simple predicate
    TerminusDB.WOQL.path("v:S", "friend", "v:O")

    # Inverse traversal
    TerminusDB.WOQL.path("v:S", "<friend", "v:O")

    # Star (zero or more)
    TerminusDB.WOQL.path("v:S", "friend*", "v:O")

    # Plus (one or more)
    TerminusDB.WOQL.path("v:S", "friend+", "v:O")

    # Bounded repetition
    TerminusDB.WOQL.path("v:S", "friend{1,3}", "v:O")

    # Alternation
    TerminusDB.WOQL.path("v:S", "friend|foe", "v:O")

    # Sequence
    TerminusDB.WOQL.path("v:S", "friend,location", "v:O")

    # Any predicate
    TerminusDB.WOQL.path("v:S", ".", "v:O")

    # Grouping
    TerminusDB.WOQL.path("v:S", "(friend|foe)*", "v:O")

## Structured patterns

    TerminusDB.WOQL.path("v:S",
      TerminusDB.WOQL.Path.path_star(TerminusDB.WOQL.Path.path_pred("friend")),
      "v:O"
    )

## Options

- A 4th argument binds the path itself to a variable.

## Examples

    iex> q = TerminusDB.WOQL.path("v:S", "friend*", "v:O")
    iex> q.op
    :path

    iex> q2 = TerminusDB.WOQL.path("v:S", "friend*", "v:O", "v:Path")
    iex> q2.args
    ["v:S", {:star, {:pred, "friend"}}, "v:O", "v:Path"]

# `path`

```elixir
@spec path(woql_node(), String.t() | tuple(), value(), woql_var()) :: t()
```

# `plus`

```elixir
@spec plus([value() | t()]) :: t()
```

Builds a `Plus` — sums a list of arithmetic values.

## Examples

    iex> q = TerminusDB.WOQL.plus(["v:X", 5, "v:Y"])
    iex> q.op
    :plus

# `post`

```elixir
@spec post(
  String.t(),
  keyword()
) :: t()
```

Builds a `QueryResource` for a file posted as part of the request.

## Examples

    iex> q = TerminusDB.WOQL.post("upload.csv")
    iex> q.op
    :post

# `put`

```elixir
@spec put([map()], t(), t()) :: t()
```

Builds a `Put` — writes an array of variables + optional column
names to a resource.

## Examples

    iex> q = TerminusDB.WOQL.put(TerminusDB.WOQL.woql_as([{"name", "v:Name"}]), TerminusDB.WOQL.triple("v:S", "p", "v:O"), TerminusDB.WOQL.file("out.csv"))
    iex> q.op
    :put

# `quad`

```elixir
@spec quad(woql_node(), woql_node(), value(), String.t()) :: t()
```

Builds a `Quad` pattern: subject, predicate, object, graph.

Quads reuse the `Triple` JSON-LD type with an added `graph` field.

## Examples

    iex> q = TerminusDB.WOQL.quad("v:S", "name", "v:N", "instance")
    iex> q.op
    :quad

# `quad_next`

```elixir
@spec quad_next(woql_node(), woql_node(), value(), value(), String.t()) :: t()
```

Builds a `TripleNext` with an explicit graph selector.

## Examples

    iex> q = TerminusDB.WOQL.quad_next("v:S", "v:P", "v:O", "v:Next", "instance")
    iex> q.op
    :triple_next

# `quad_previous`

```elixir
@spec quad_previous(woql_node(), woql_node(), value(), value(), String.t()) :: t()
```

Builds a `TriplePrevious` with an explicit graph selector.

## Examples

    iex> q = TerminusDB.WOQL.quad_previous("v:S", "v:P", "v:O", "v:Prev", "instance")
    iex> q.op
    :triple_previous

# `quad_slice`

```elixir
@spec quad_slice(woql_node(), woql_node(), value(), value(), value(), String.t()) ::
  t()
```

Builds a `TripleSlice` with an explicit graph selector.

## Examples

    iex> q = TerminusDB.WOQL.quad_slice("v:S", "v:P", "v:O", 10, 100, "instance")
    iex> q.op
    :triple_slice

# `quad_slice_rev`

```elixir
@spec quad_slice_rev(woql_node(), woql_node(), value(), value(), value(), String.t()) ::
  t()
```

Builds a `TripleSliceRev` with an explicit graph selector.

## Examples

    iex> q = TerminusDB.WOQL.quad_slice_rev("v:S", "v:P", "v:O", 10, 100, "instance")
    iex> q.op
    :triple_slice_rev

# `random_idgen`

```elixir
@spec random_idgen(String.t(), woql_var()) :: t()
```

Alias for `idgen_random/2`.

# `range_max`

```elixir
@spec range_max(value(), value()) :: t()
```

Builds a `RangeMax` — find maximum value in a list (any comparable
types).

## Examples

    iex> q = TerminusDB.WOQL.range_max("v:List", "v:Max")
    iex> q.op
    :range_max

# `range_min`

```elixir
@spec range_min(value(), value()) :: t()
```

Builds a `RangeMin` — find minimum value in a list (any comparable
types).

## Examples

    iex> q = TerminusDB.WOQL.range_min("v:List", "v:Min")
    iex> q.op
    :range_min

# `read_document`

```elixir
@spec read_document(String.t(), woql_var()) :: t()
```

Builds a `ReadDocument` that reads a document by ID into a variable.

## Examples

    iex> q = TerminusDB.WOQL.read_document("Person/Alice", "v:Doc")
    iex> q.op
    :read_document

# `regexp`

```elixir
@spec regexp(value(), value(), value()) :: t()
```

Builds a `Regexp` — regex match; `result_list` captures groups.

## Examples

    iex> q = TerminusDB.WOQL.regexp("pattern", "v:String", "v:Result")
    iex> q.op
    :regexp

# `remote`

```elixir
@spec remote(
  String.t(),
  keyword()
) :: t()
```

Builds a `QueryResource` for a remote URL data source.

## Examples

    iex> q = TerminusDB.WOQL.remote("https://example.com/data.csv")
    iex> q.op
    :remote

# `removed_quad`

```elixir
@spec removed_quad(woql_node(), woql_node(), value(), String.t()) :: t()
```

Builds a `DeletedTriple` with a graph — a quad removed in the current commit.

## Examples

    iex> q = TerminusDB.WOQL.removed_quad("v:S", "name", "v:N", "instance")
    iex> q.op
    :removed_quad

# `removed_triple`

```elixir
@spec removed_triple(woql_node(), woql_node(), value()) :: t()
```

Builds a `DeletedTriple` — a triple removed in the current commit.

## Examples

    iex> q = TerminusDB.WOQL.removed_triple("v:S", "name", "v:N")
    iex> q.op
    :removed_triple

# `select`

```elixir
@spec select([woql_var()], t()) :: t()
```

Builds a `Select` that projects the given variables from a sub-query.

`vars` is a list of variable names (e.g. `["v:Name", "v:Person"]`).

## Examples

    iex> q = TerminusDB.WOQL.select(["v:Name"],
    ...>   TerminusDB.WOQL.and_([
    ...>     TerminusDB.WOQL.triple("v:Person", "name", "v:Name")
    ...>   ])
    ...> )
    iex> q.op
    :select

# `sequence`

```elixir
@spec sequence(value(), value(), value(), value() | nil, value() | nil) :: t()
```

Builds a `Sequence` — generates a sequence of values in half-open
[start, end) via backtracking. `step` and `count` are optional
(default `nil`).

## Examples

    iex> q = TerminusDB.WOQL.sequence("v:V", 1, 10)
    iex> q.op
    :sequence

# `set_difference`

```elixir
@spec set_difference(value(), value(), value()) :: t()
```

Builds a `SetDifference`.

## Examples

    iex> q = TerminusDB.WOQL.set_difference("v:A", "v:B", "v:Result")
    iex> q.op
    :set_difference

# `set_intersection`

```elixir
@spec set_intersection(value(), value(), value()) :: t()
```

Builds a `SetIntersection`.

## Examples

    iex> q = TerminusDB.WOQL.set_intersection("v:A", "v:B", "v:Result")
    iex> q.op
    :set_intersection

# `set_member`

```elixir
@spec set_member(value(), value()) :: t()
```

Builds a `SetMember` — membership test in a set.

## Examples

    iex> q = TerminusDB.WOQL.set_member("v:Item", "v:Set")
    iex> q.op
    :set_member

# `set_union`

```elixir
@spec set_union(value(), value(), value()) :: t()
```

Builds a `SetUnion`.

## Examples

    iex> q = TerminusDB.WOQL.set_union("v:A", "v:B", "v:Result")
    iex> q.op
    :set_union

# `size`

```elixir
@spec size(String.t(), value()) :: t()
```

Builds a `Size` — binds the size (bytes) of a graph.

## Examples

    iex> q = TerminusDB.WOQL.size("instance", "v:Size")
    iex> q.op
    :size

# `slice`

```elixir
@spec slice(value(), value(), value(), value() | nil) :: t()
```

Builds a `Slice` — slices a list `[start, end)`.

## Examples

    iex> q = TerminusDB.WOQL.slice("v:List", "v:Result", 0, 5)
    iex> q.op
    :slice

# `split`

```elixir
@spec split(value(), value(), value()) :: t()
```

Builds a `Split` — splits a string by `glue` into a list.

## Examples

    iex> q = TerminusDB.WOQL.split("v:String", ",", "v:Result")
    iex> q.op
    :split

# `star`

```elixir
@spec star() :: t()
```

Builds a `star` query — selects everything as triples with default
variables `v:Subject`, `v:Predicate`, `v:Object`.

## Examples

    iex> q = TerminusDB.WOQL.star()
    iex> q.op
    :triple

# `start`

```elixir
@spec start(non_neg_integer(), t()) :: t()
```

Builds a `Start` — offset (start index) for results.

## Examples

    iex> q = TerminusDB.WOQL.start(5, TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :start

# `string`

```elixir
@spec string(String.t()) :: map()
```

Wraps a string as an `xsd:string` literal dict.

## Examples

    iex> TerminusDB.WOQL.string("hello")
    %{"@type" => "xsd:string", "@value" => "hello"}

# `sub`

```elixir
@spec sub(woql_node(), woql_node()) :: t()
```

Builds a `Subsumption` — true if `child` is a subclass of `parent`.

## Examples

    iex> q = TerminusDB.WOQL.sub(WOQL.iri("@schema:Animal"), WOQL.iri("@schema:Dog"))
    iex> q.op
    :sub

# `substr`

```elixir
@spec substr(value(), value(), value(), value(), value()) :: t()
```

Builds a `Substring` — extracts a substring with `before`/`length`/`after`.

## Examples

    iex> q = TerminusDB.WOQL.substr("v:String", 5, "v:Sub", 0, 0)
    iex> q.op
    :substr

# `substring`

```elixir
@spec substring(value(), value(), value(), value(), value()) :: t()
```

Alias for `substr/5`.

# `subsumption`

```elixir
@spec subsumption(woql_node(), woql_node()) :: t()
```

Alias for `sub/2`.

# `sum`

```elixir
@spec sum(value(), value()) :: t()
```

Builds a `Sum` — sums a list of numbers into a single value.

## Examples

    iex> q = TerminusDB.WOQL.sum("v:List", "v:Result")
    iex> q.op
    :sum

# `times`

```elixir
@spec times([value() | t()]) :: t()
```

Builds a `Times` — multiplies a list of arithmetic values.

## Examples

    iex> q = TerminusDB.WOQL.times(["v:X", 5])
    iex> q.op
    :times

# `to_jsonld`

```elixir
@spec to_jsonld(t()) :: map()
```

Serializes a `WOQL.Query` to the JSON-LD wire format expected by the
`/api/woql` endpoint.

## Examples

    iex> q = TerminusDB.WOQL.triple("v:S", "name", "v:N")
    iex> jsonld = TerminusDB.WOQL.to_jsonld(q)
    iex> jsonld["@type"]
    "Triple"

# `trim`

```elixir
@spec trim(value(), value()) :: t()
```

Builds a `Trim` — strips leading/trailing whitespace.

## Examples

    iex> q = TerminusDB.WOQL.trim("v:Untrimmed", "v:Trimmed")
    iex> q.op
    :trim

# `triple`

```elixir
@spec triple(woql_node(), woql_node(), value()) :: t()
```

Builds a `Triple` pattern: subject, predicate, object.

Any argument can be a variable (`"v:Name"`) or a constant.

## Examples

    iex> q = TerminusDB.WOQL.triple("v:Person", "name", "v:Name")
    iex> q.op
    :triple

# `triple_count`

```elixir
@spec triple_count(String.t(), value()) :: t()
```

Builds a `TripleCount` — binds the number of triples in a graph.

## Examples

    iex> q = TerminusDB.WOQL.triple_count("instance", "v:Count")
    iex> q.op
    :triple_count

# `triple_next`

```elixir
@spec triple_next(woql_node(), woql_node(), value(), value()) :: t()
```

Builds a `TripleNext` — finds the next object value after a reference.
When object is bound and next is free, finds the smallest next > object.

## Examples

    iex> q = TerminusDB.WOQL.triple_next("v:S", "v:P", "v:O", "v:Next")
    iex> q.op
    :triple_next

# `triple_previous`

```elixir
@spec triple_previous(woql_node(), woql_node(), value(), value()) :: t()
```

Builds a `TriplePrevious` — finds the previous object value before a
reference. When object is bound and previous is free, finds the largest
previous < object.

## Examples

    iex> q = TerminusDB.WOQL.triple_previous("v:S", "v:P", "v:O", "v:Prev")
    iex> q.op
    :triple_previous

# `triple_slice`

```elixir
@spec triple_slice(woql_node(), woql_node(), value(), value(), value()) :: t()
```

Builds a `TripleSlice` — triple pattern with half-open value range
[low, high) on the object.

## Examples

    iex> q = TerminusDB.WOQL.triple_slice("v:S", "v:P", "v:O", 10, 100)
    iex> q.op
    :triple_slice

# `triple_slice_rev`

```elixir
@spec triple_slice_rev(woql_node(), woql_node(), value(), value(), value()) :: t()
```

Builds a `TripleSliceRev` — same as `triple_slice/5` but iterates in
descending order (high to low).

## Examples

    iex> q = TerminusDB.WOQL.triple_slice_rev("v:S", "v:P", "v:O", 10, 100)
    iex> q.op
    :triple_slice_rev

# `true_`

```elixir
@spec true_() :: t()
```

Builds a `True` constant query.

## Examples

    iex> q = TerminusDB.WOQL.true_()
    iex> q.op
    :true

# `type_of`

```elixir
@spec type_of(woql_node(), woql_var()) :: t()
```

Builds a `TypeOf` that unifies the type of a node with a variable.

## Examples

    iex> q = TerminusDB.WOQL.type_of("v:Person", "v:Type")
    iex> q.op
    :type_of

# `typecast`

```elixir
@spec typecast(value(), value(), value()) :: t()
```

Alias for `cast/3`.

# `unique`

```elixir
@spec unique(String.t(), [value()], woql_var()) :: t()
```

Builds a `HashKey` — deterministic hash ID from a key list.

## Examples

    iex> q = TerminusDB.WOQL.unique("Person/", ["v:Name", "v:Email"], "v:ID")
    iex> q.op
    :unique

# `update_document`

```elixir
@spec update_document(value(), woql_node() | nil) :: t()
```

Builds an `UpdateDocument` — insert-or-replace a document.

`identifier` is a variable (e.g. `"v:Id"`) that will be bound to the
updated document's IRI.

## Examples

    iex> q = TerminusDB.WOQL.update_document("v:Doc")
    iex> q.op
    :update_document

    iex> q = TerminusDB.WOQL.update_document(%{"@type" => "Person"}, "v:Id")
    iex> q.op
    :update_document

# `update_quad`

```elixir
@spec update_quad(woql_node(), woql_node(), value(), String.t()) :: t()
```

Composes an update: optionally delete any existing quad, then add the new
one.

The internal variable `"v:OldObject"` is used to match any existing object
before deletion. Avoid using `"v:OldObject"` as a variable in surrounding
queries to prevent unintended unification.

## Examples

    iex> q = TerminusDB.WOQL.update_quad("v:S", "name", "Alice", "instance")
    iex> q.op
    :and

# `update_triple`

```elixir
@spec update_triple(woql_node(), woql_node(), value()) :: t()
```

Composes an update: optionally delete any existing triple, then add the new
one. Equivalent to `and_([opt(delete_triple(s, p, "v:OldObject")), add_triple(s, p, o)])`.

The internal variable `"v:OldObject"` is used to match any existing object
before deletion. Avoid using `"v:OldObject"` as a variable in surrounding
queries to prevent unintended unification.

## Examples

    iex> q = TerminusDB.WOQL.update_triple("v:S", "name", "Alice")
    iex> q.op
    :and

# `upper`

```elixir
@spec upper(value(), value()) :: t()
```

Builds an `Upper` — converts to uppercase.

## Examples

    iex> q = TerminusDB.WOQL.upper("v:Input", "v:Result")
    iex> q.op
    :upper

# `using`

```elixir
@spec using(String.t(), t()) :: t()
```

Builds a `Using` — scopes the enclosed query to a data product / collection.

## Examples

    iex> q = TerminusDB.WOQL.using("mydb", TerminusDB.WOQL.triple("v:S", "p", "v:O"))
    iex> q.op
    :using

# `var`

```elixir
@spec var(String.t()) :: String.t()
```

Wraps a name as a WOQL variable string (`"v:Name"`).

## Examples

    iex> TerminusDB.WOQL.var("Person")
    "v:Person"

# `weekday`

```elixir
@spec weekday(value(), value()) :: t()
```

Builds a `Weekday` — computes ISO 8601 weekday number (Monday=1,
Sunday=7).

## Examples

    iex> q = TerminusDB.WOQL.weekday("v:Date", "v:Day")
    iex> q.op
    :weekday

# `weekday_sunday_start`

```elixir
@spec weekday_sunday_start(value(), value()) :: t()
```

Builds a `WeekdaySundayStart` — computes US-convention weekday
(Sunday=1, Saturday=7).

## Examples

    iex> q = TerminusDB.WOQL.weekday_sunday_start("v:Date", "v:Day")
    iex> q.op
    :weekday_sunday_start

# `woql_as`

```elixir
@spec woql_as([{String.t() | non_neg_integer(), woql_var()}]) :: [map()]
```

Builds a list of `Column`/`Indicator` JSON-LD objects for use with
`get/2` and `put/3`.

Accepts a list of `{name_or_index, variable}` tuples.

## Examples

    iex> cols = TerminusDB.WOQL.woql_as([{"name", "v:Name"}, {0, "v:Idx"}])
    iex> length(cols)
    2
    iex> hd(cols)["@type"]
    "Column"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
