> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wirekite.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Limitations

> What Sumatra deliberately rejects, what is absent from the current release, and the operational boundaries to plan around.

Sumatra's design stance is that a limitation should be a **loud
compile-time rejection with a named reason**, not a silent performance
cliff or a wrong value discovered in production. This page collects the
boundaries: permanent ones (rejected on principle), release ones (not
in 0.2.0), and operational ones (true today, worth planning around).

## Permanent, by design

These are not roadmap items — they define the execution model.

* **No per-row server operations.** A per-row server query or write —
  the cursor-style pattern from OLTP databases — is inexpressible by
  grammar. All server interaction is batched.
* **No nested read blocks**, and no read inside a compute loop.
  Decorrelate with a JOIN in the read, or load the inner table as a
  [keyed collection](/sumatra/language#collections) and probe it.
* **No unbounded server-dependent loops.** A `WHILE` that needs fresh
  server data each iteration to decide termination does not fit the
  read → compute → write model and is rejected.
* **`ORDER KEY` columns must be `INT`, `BIGINT`, or `TIMESTAMP`.**
  Floats are excluded on principle (float equality is unsound as a
  cursor); `DATE` is excluded because keyset pagination over a
  one-value-per-day key cannot make progress within a day.
* **No text-crossing casts in compute.** `TEXT` → number or number →
  `TEXT` conversions belong in the read's SQL, where the engine's full
  conversion machinery (and error surface) applies.
* **A write cannot change its own merge key.** `SET` of a key column,
  or a `SET ROW` matched on anything other than the record's own key
  field, is a compile error.
* **One change per key per batch.** Duplicate writes to one merge key
  in a flush unit are a program error, surfaced loudly (repeated
  DELETEs excepted).
* **Bare table names only.** No `schema.table` qualification, and
  engine identifiers must be usable unquoted — reach exotic names by
  aliasing them inside the read's SQL. Identifiers are ASCII.

## Not in this release

Absent from 0.2.0; some are roadmapped, none are promised here:

* **User-defined functions** (`FUNCTION` / `RETURN expr` are reserved
  words today).
* **User-defined exceptions** — the catchable set is `ZERO_DIVIDE`,
  `OVERFLOW`, `NO_DATA_FOUND`, `OTHERS`.
* **Iterating or aggregating a collection.** Keyed maps are probe-only
  lookups: no `FOR x IN map`, no `.COUNT`, no in-memory `SUM` over a
  map. Aggregate in the read instead.
* **`BYTEA` and `ARRAY` in compute.** Both types carry fine through
  server-side statements; neither can enter an in-memory record.
* **Regex, format masks, and transcendental math** in compute position
  (`REGEXP_*`, `TO_CHAR`/`TO_DATE`, `POWER`/`EXP`/`LN`/trig — `SQRT`
  is the exception). Use them in the read's SQL.
* **Loop labels** (`EXIT` always exits the innermost loop), procedure
  calling procedure, and the `!=` spelling (use `<>`).
* **`EXEC` literal escaping** — a text argument containing a single
  quote cannot be passed.

## PL/SQL features deliberately not carried over

For readers arriving from Oracle: explicit cursors and cursor
attributes (`%FOUND`, `%NOTFOUND`, `%ROWCOUNT`), `FORALL`, `GOTO`,
packages, overloading, autonomous transactions, `SAVEPOINT`, explicit
`ROLLBACK` (a fault's rollback is automatic; graceful stops are the
`EXCEPTION` block's job), dynamic SQL (`EXECUTE IMMEDIATE`), `%TYPE`,
`CONSTANT`, and declaration `DEFAULT`/`NOT NULL` modifiers. `VARRAY`,
nested tables, and `MULTISET` are replaced by the single keyed-map
collection.

## Operational boundaries

* **Firebolt is the only live backend in this release.** The
  toolchain is engine-neutral by construction — the DSN scheme
  declares the backend, and everything engine-specific lives behind
  per-backend profiles — but `firebolt` is the only scheme that binds
  today.
* **Linux x86-64 only**, and compiling hosts need `g++`, `pkg-config`,
  and libcurl headers. (Hosts that only run cached stored procedures
  need none of that.)
* **Compiling requires a live connection** — the connected database is
  the schema. The offline `sumatra-compile` tool works only against
  its built-in sample schema.
* **`BATCH SIZE ALL` on a compute path holds the whole result in
  client memory.** A result that does not fit is a loud fault, not a
  spill. Chunk with `BATCH SIZE N` where results are large.
* **Aggregating reads re-evaluate per chunk** under `BATCH SIZE N` —
  use `BATCH SIZE ALL` for `GROUP BY` sources.
* **The `sumatra_` prefix is reserved** in target databases: the
  toolchain creates and drops `sumatra_stage_*` and
  `sumatra_stage_lock_*` tables and owns `sumatra_source`. It also
  reserves one staging column name on its own staging tables. There is
  no collision guard — keep your own objects off the prefix.
* **DSN files are plaintext** — protect them with file permissions
  (`chmod 600`). There is no encrypted-DSN mechanism in this release.
* **Concurrent identical runs are refused.** The same procedure with
  the same argument values will not start twice at once (a stale lock
  from a crashed run clears itself after a timeout).
* **The shell is one statement per line** — no multi-line input, no
  SQL passthrough.
* **Shared host cache across accounts.** Two same-named databases on
  different Firebolt accounts share one per-host binary-cache
  directory; prefer distinct database names.
* **One exotic cursor edge:** a row whose `ORDER KEY` value equals the
  exact type minimum (`INT`/`BIGINT` minimum, or timestamp
  `0001-01-01 00:00:00`) is never fetched by a chunked read. Real keys
  never live there; synthetic sentinel keys should not.

## Reading an error you did not expect

Compile-time rejections name the rule that fired and, where one
exists, the supported alternative — the error text is the
documentation of first resort. If a program you believe should compile
is rejected, check this page's permanent list first, then
[Programs and batches](/sumatra/programs) for the structural rules
(commit placement, `ORDER KEY` requirements, write shapes).
