# gizweb:view

one view of a relation for the grid, the pivot, the charts, the board, the timeline, the calendar and the gallery. A view is a Spec (fields, sort, filters, search, groups, measures, pivot). The server compiles it to the SQL of the relation's dialect, runs it bounded by what one screen shows, and answers with a binary columnar frame (GZV1) or JSON. The database computes and reduces; the browser keeps only the windows it shows. A page's tables answer at `/_view/NAME` through the Gate (`gate`); a product mounts another relation, such as an external database, with `source` and `handle`. Every value of a Spec becomes a quoted literal or a checked number, and every name must be a column of the relation, so a Spec cannot become other SQL.

```gizlang
import * as View from "gizweb:view";
```

## Types

### `Sort`

```gizlang
type Sort = { field: string; desc?: bool; }
```

An order of the view: a column, descending or not.

- `field`: `string`
- `desc`: `_gizlang_sdk_core.Option<bool>`

### `Filter`

```gizlang
type Filter = { field: string; op: string; values?: Vec<string>; }
```

A condition on a column. OP is eq, ne, lt, le, gt, ge, between (two values), in, out (any values), contains, starts, ends, null or notnull.

- `field`: `string`
- `op`: `string`
- `values`: `_gizlang_sdk_core.Option<Vec<string>>`

### `Measure`

```gizlang
type Measure = { field: string; agg: string; expr?: string; name?: string; }
```

An aggregate of a column: AGG (one of AGGREGATES) of FIELD (count of `*` counts rows). With EXPR it is instead a measure expression
(`expression`) over aggregates, such as `sum(amount) / count()` or `sum(amount) / total(sum(amount))`, and NAME is what people read.

- `field`: `string`
- `agg`: `string`
- `expr`: `_gizlang_sdk_core.Option<string>`
- `name`: `_gizlang_sdk_core.Option<string>`

### `Computed`

```gizlang
type Computed = { name: string; expr: string; }
```

A calculated column: NAME, and EXPR, an expression over the columns (and the calculated columns before it) that the database computes
(`expression`).

- `name`: `string`
- `expr`: `string`

### `Spec`

```gizlang
type Spec = { fields?: Vec<string>; sort?: Vec<Sort>; filters?: Vec<Filter>; search?: string; groups?: Vec<string>; measures?: Vec<Measure>; pivot?: Vec<string>; computed?: Vec<Computed>; where?: string; }
```

One view of a relation. FIELDS empty is every column; COMPUTED adds calculated columns. WHERE is a condition in the expression language
(`expression`) that every row of the view meets, beside FILTERS.

- `fields`: `_gizlang_sdk_core.Option<Vec<string>>`
- `sort`: `_gizlang_sdk_core.Option<Vec<M104.Sort>>`
- `filters`: `_gizlang_sdk_core.Option<Vec<M104.Filter>>`
- `search`: `_gizlang_sdk_core.Option<string>`
- `groups`: `_gizlang_sdk_core.Option<Vec<string>>`
- `measures`: `_gizlang_sdk_core.Option<Vec<M104.Measure>>`
- `pivot`: `_gizlang_sdk_core.Option<Vec<string>>`
- `computed`: `_gizlang_sdk_core.Option<Vec<M104.Computed>>`
- `where`: `_gizlang_sdk_core.Option<string>`

### `Cube`

```gizlang
type Cube = { x: string; lo: f64; hi: f64; buckets: i64; }
```

The cube of a reduction for a brush of the column X over LO..HI (axis units: milliseconds for a time) in BUCKETS steps: each group
of the reduction once per step, its measure in parts that add up (`giz_sum` and `giz_count` for an average), so a linked chart draws
any brush of those steps itself, however many rows the relation holds.

- `x`: `string`
- `lo`: `f64`
- `hi`: `f64`
- `buckets`: `i64`

### `Reduce`

```gizlang
type Reduce = { kind: string; x?: string; y?: string; series?: string; agg?: string; expr?: string; buckets?: i64; ybuckets?: i64; top?: i64; cube?: Cube; }
```

The reduction of a view: its KIND, the columns X, Y and SERIES, the aggregate AGG, the buckets and TOP, and the CUBE.

- `kind`: `string`
- `x`: `_gizlang_sdk_core.Option<string>`
- `y`: `_gizlang_sdk_core.Option<string>`
- `series`: `_gizlang_sdk_core.Option<string>`
- `agg`: `_gizlang_sdk_core.Option<string>`
- `expr`: `_gizlang_sdk_core.Option<string>`
- `buckets`: `_gizlang_sdk_core.Option<i64>`
- `ybuckets`: `_gizlang_sdk_core.Option<i64>`
- `top`: `_gizlang_sdk_core.Option<i64>`
- `cube`: `_gizlang_sdk_core.Option<M104.Cube>`

### `Cell`

```gizlang
type Cell = { name: string; value?: string; }
```

One cell of a row to add: a column and its wire text (none: NULL).

- `name`: `string`
- `value`: `_gizlang_sdk_core.Option<string>`

### `Edit`

```gizlang
type Edit = { op?: string; key?: Vec<string>; name?: string; value?: string; before?: string; check?: bool; row?: Vec<Cell>; }
```

One change of `apply`. `set` (the default) sets the column NAME of the row KEY (its key columns' wire texts, in order) to VALUE (none:
NULL); with CHECK it is refused as a conflict when the column no longer holds BEFORE (none: NULL). `insert` adds ROW, `delete` removes KEY.

- `op`: `_gizlang_sdk_core.Option<string>`
- `key`: `_gizlang_sdk_core.Option<Vec<string>>`
- `name`: `_gizlang_sdk_core.Option<string>`
- `value`: `_gizlang_sdk_core.Option<string>`
- `before`: `_gizlang_sdk_core.Option<string>`
- `check`: `_gizlang_sdk_core.Option<bool>`
- `row`: `_gizlang_sdk_core.Option<Vec<M104.Cell>>`

### `Ask`

```gizlang
type Ask = { op: string; spec?: Spec; from?: i64; count?: i64; total?: bool; by?: Vec<string>; path?: Vec<Option<string>>; after?: Vec<Option<string>>; skip?: i64; field?: string; like?: string; reduce?: Reduce; changes?: Vec<Edit>; format?: string; protect?: bool; title?: string; save?: string; data?: string; columns?: Vec<string>; dry?: bool; keys?: Vec<Vec<string>>; key?: Vec<string>; body?: string; }
```

A request of a view. OP is describe, rows, aggregate, profile, values, reduce, apply, export, import, notes or note.
FROM and COUNT page `rows`, `aggregate` and `values`; TOTAL asks the count of all rows (or groups) as well. `aggregate` groups by BY,
inside the group PATH of the Spec's groups (none in PATH is NULL). AFTER (the order values of a row, sort fields then keys; none for
NULL) starts a `rows` window just after that row, SKIP rows further, instead of at FROM: a keyed view then never reads the rows before
it. `marks` answers the order values of every COUNT-th row, where a jump starts its window. FIELD is the column of `values`; LIKE
narrows it. `profile` answers a profile of each of COLUMNS, in one scan.
`export` writes FORMAT (one of FORMATS, csv the default): a workbook sheet is read-only with PROTECT, a PDF has TITLE over its table, and
with SAVE the file is kept under that name where the host keeps files (`Opened.save`) instead of answered. `import` reads DATA, a CSV
or XLSX file (FORMAT) in base64, whose first row names its columns; COLUMNS gives the view column of each file column ("" leaves it out,
a missing one is the column of that name or label), and DRY answers the preview without inserting. `notes` answers the notes of the cells
of the rows KEYS where the host keeps them (`Opened.notes`); `note` keeps BODY as the note of the cell of the row KEY and the column
FIELD (an empty BODY removes it).

- `op`: `string`
- `spec`: `_gizlang_sdk_core.Option<M104.Spec>`
- `from`: `_gizlang_sdk_core.Option<i64>`
- `count`: `_gizlang_sdk_core.Option<i64>`
- `total`: `_gizlang_sdk_core.Option<bool>`
- `by`: `_gizlang_sdk_core.Option<Vec<string>>`
- `path`: `_gizlang_sdk_core.Option<Vec<_gizlang_sdk_core.Option<string>>>`
- `after`: `_gizlang_sdk_core.Option<Vec<_gizlang_sdk_core.Option<string>>>`
- `skip`: `_gizlang_sdk_core.Option<i64>`
- `field`: `_gizlang_sdk_core.Option<string>`
- `like`: `_gizlang_sdk_core.Option<string>`
- `reduce`: `_gizlang_sdk_core.Option<M104.Reduce>`
- `changes`: `_gizlang_sdk_core.Option<Vec<M104.Edit>>`
- `format`: `_gizlang_sdk_core.Option<string>`
- `protect`: `_gizlang_sdk_core.Option<bool>`
- `title`: `_gizlang_sdk_core.Option<string>`
- `save`: `_gizlang_sdk_core.Option<string>`
- `data`: `_gizlang_sdk_core.Option<string>`
- `columns`: `_gizlang_sdk_core.Option<Vec<string>>`
- `dry`: `_gizlang_sdk_core.Option<bool>`
- `keys`: `_gizlang_sdk_core.Option<Vec<Vec<string>>>`
- `key`: `_gizlang_sdk_core.Option<Vec<string>>`
- `body`: `_gizlang_sdk_core.Option<string>`

### `Column`

```gizlang
type Column = { name: string; label: string; ty: Type; key: bool; editable: bool; nullable: bool; values: Vec<string>; kind?: string; }
```

A column of the relation: its SQL name, what people read, its type, and whether it is a key, may be changed and may be NULL. VALUES
are the choices of its value; KIND, the no-code field kind that the grid shows and edits it as (none: as its type).

- `name`: `string`
- `label`: `string`
- `ty`: `M80.Type`
- `key`: `bool`
- `editable`: `bool`
- `nullable`: `bool`
- `values`: `Vec<string>`
- `kind`: `_gizlang_sdk_core.Option<string>`

### `Fetched`

```gizlang
type Fetched = { types: Vec<Type>; rows: Vec<Vec<Value>>; }
```

Rows that a runner read, with the type of each column.

- `types`: `Vec<M80.Type>`
- `rows`: `Vec<Vec<M80.Value>>`

### `Runner`

```gizlang
type Runner = { dialect: string; relation: string; columns: Vec<Column>; writable: bool; fetch: (sql: string, outputs: Vec<Typed.Slot>, max: i64) => Fetched throws Model.Rejection; apply: (changes: Vec<Edit>) => i64 throws Model.Rejection; target?: string; }
```

One relation that views read: its dialect, its SQL (a table or a parenthesized query), its columns, how to read a SELECT over it (with
the result's slots, nameless, for a typed source) and how to apply changes in one transaction.

- `dialect`: `string`
- `relation`: `string`
- `columns`: `Vec<M104.Column>`
- `writable`: `bool`
- `fetch`: `(sql: string, outputs: Vec<M79.Slot>, max: i64) => M104.Fetched throws M72.Rejection`
- `apply`: `(changes: Vec<M104.Edit>) => i64 throws M72.Rejection`
- `target`: `_gizlang_sdk_core.Option<string>` — The table that changes go to when RELATION is a query over it, as a relation with computed columns is (none: RELATION).

### `Saving`

```gizlang
type Saving = (name: string, write: (stream: Stream) => i64 throws IoError) => string throws Model.Rejection
```

Where a host keeps a file: the file NAME, filled by WRITE through its stream. Answers where it was kept.

### `Note`

```gizlang
type Note = { key: Vec<string>; field: string; body: string; author: string; at: i64; }
```

A note on the cell of the row KEY (its key values, as a frame writes them) and the column FIELD: BODY, by AUTHOR at AT (milliseconds
since 1970).

- `key`: `Vec<string>`
- `field`: `string`
- `body`: `string`
- `author`: `string`
- `at`: `i64`

### `Revision`

```gizlang
type Revision = { field: string; before?: string; after?: string; author: string; at: i64; }
```

One change of a cell of the row a history is of: its column FIELD from BEFORE to AFTER (none: NULL), by AUTHOR at AT.

- `field`: `string`
- `before`: `_gizlang_sdk_core.Option<string>`
- `after`: `_gizlang_sdk_core.Option<string>`
- `author`: `string`
- `at`: `i64`

### `Noting`

```gizlang
type Noting = { read: (keys: Vec<Vec<string>>) => Vec<Note> throws Model.Rejection; write: (key: Vec<string>, field: string, body: string) => Note throws Model.Rejection; history?: (key: Vec<string>) => Vec<Revision> throws Model.Rejection; }
```

Where a host keeps the notes of a view's cells, one per cell: READ gives those of the rows KEYS, WRITE keeps BODY as the note of a cell
(an empty BODY removes it) and answers it. HISTORY, when the host keeps it, gives the changes of the row KEY, newest first. Who may read
and write them is the host's to decide.

- `read`: `(keys: Vec<Vec<string>>) => Vec<M104.Note> throws M72.Rejection`
- `write`: `(key: Vec<string>, field: string, body: string) => M104.Note throws M72.Rejection`
- `history`: `_gizlang_sdk_core.Option<(key: Vec<string>) => Vec<M104.Revision> throws M72.Rejection>`

### `Opened`

```gizlang
type Opened = { runner: Runner; close: () => void; save: Option<Saving>; notes: Option<Noting>; }
```

A view that is open: its runner, what to release once it answered (a connection), where its exports are kept as files and where the
notes of its cells are kept (none: the host keeps none).

- `runner`: `M104.Runner`
- `close`: `() => void`
- `save`: `_gizlang_sdk_core.Option<(name: string, write: (stream: gizlang_system.Stream) => i64 throws gizlang_system.IoError) => string throws M72.Rejection>`
- `notes`: `_gizlang_sdk_core.Option<M104.Noting>`

## Functions

### `expression`

```gizlang
function expression(r: Runner, expr: string): Compiled throws Model.Rejection
```

EXPR, an expression over the columns of R, as SQL and its type.

Effects: fail, read, write, console, io.

### `computed`

```gizlang
function computed(r: Runner, spec: Spec): Runner throws Model.Rejection
```

R with the calculated columns of SPEC: each wraps the relation in a SELECT that adds its column, so it sorts, filters, groups, pivots,
reduces and exports as a stored column does, and a later one may name an earlier one. A calculated column is never edited.

Effects: fail, read, write, console, io.

### `frame`

```gizlang
function frame(names: Vec<string>, fetched: Fetched, total: i64, from: i64, keys: Vec<string>): bytes
```

NAMES and ROWS as a GZV1 frame: `GZV1`, the head's byte length (u32), the head (JSON: columns, rows, total, from, keys), then each
column: a null bitmap of ceil(rows / 8) bytes (bit set: NULL), then its values (i64, f64, a byte, or a dictionary: u32 count, each entry
u32 length and UTF-8 bytes, then a u32 code for each row).

Effects: fail.

### `selectSql`

```gizlang
function selectSql(r: Runner, ask: Ask): string throws Model.Rejection
```

The SELECT of a window of rows (OP "rows") or of groups (OP "aggregate"), for a product that runs it itself or shows it, as an agent's
answer does.

Effects: fail, read, write, console, io.

### `answer`

```gizlang
function answer(r: Runner, ask: Ask, keeps: bool, notes: bool, history: bool = false): Http.Response throws Model.Rejection
```

The answer to ASK of the relation of R; KEEPS, NOTES and HISTORY say that the host keeps exports as files, notes of cells and the
changes of rows (`describe` tells the element).

Effects: fail, read, write, console, io.

### `held`

```gizlang
function held(r: Runner): Opened
```

The view of R, which holds nothing to release and keeps no files or notes.

### `handle`

```gizlang
function handle(request: Http.Request, view: Result<Opened, Model.Rejection>): Http.Response
```

The answer to a POST of a JSON Ask to VIEW, which is released once it answered. A refusal is JSON: a view is called by its element,
never by a form.

Effects: fail, read, write, console, io.

### `gate`

```gizlang
function gate(s: Data.Scoped, shape: Model.Shape, sys: System): Runner throws Model.Rejection
```

The table of SHAPE as the actor of S may read it: the Gate's query of its rows (masks included) is the relation, and a change is a patch,
an insert or a delete through the Gate, all in one transaction. A hidden field is not a column of the view, unless it is a key.

Effects: fail, read, write, console, io.

### `hosted`

```gizlang
function hosted(context: Table.Context, shapes: Vec<Model.Shape>, name: string): Runner throws Model.Rejection
```

The view of the table NAME of the host (one of SHAPES) as the person of CONTEXT may use it.

Effects: fail, read, write, console, io.

### `serve`

```gizlang
function serve(context: Table.Context, shapes: Vec<Model.Shape>, request: Http.Request): Http.Response
```

The answer to a request at `/_view/NAME`.

Effects: fail, read, write, console, io.

### `source`

```gizlang
function source(src: Source.Source, relation: string, keys: Vec<string>, apply: Option<(changes: Vec<Edit>) => i64 throws Model.Rejection>): Runner throws Model.Rejection
```

A relation of the source SRC: RELATION is a table path or a parenthesized SELECT. Its columns are the source's (a key column named in
KEYS may identify a row); APPLY, when given, applies changes in one transaction, so the view may change rows.

Effects: fail, read, write, console, io.

### `editSql`

```gizlang
function editSql(r: Runner, changes: Vec<Edit>): Vec<string> throws Model.Rejection
```

The SQL of CHANGES to R, whose relation is a table path (not a SELECT): one statement each, which changes exactly one row. A `set` with
CHECK compares the value it replaces too, so a statement that changes no row means the row changed since it was read.

Effects: fail.

## Constants

### `FRAME`

```gizlang
const FRAME = "application/vnd.gizlang.view"
```

The media type of a frame.

### `WINDOW`

```gizlang
const WINDOW = 10000
```

The most rows of one window, one group level or one reduction.

### `PIVOT_CELLS`

```gizlang
const PIVOT_CELLS = 200000
```

The most cells of a pivot (rows times columns times measures).

### `EXPORT_ROWS`

```gizlang
const EXPORT_ROWS = 1000000
```

The most rows of an export.

### `CHANGES`

```gizlang
const CHANGES = 100000
```

The most changes of one `apply`, and rows of one import: each goes in one transaction.

### `FORMATS`

```gizlang
const FORMATS = ["csv", "xlsx", "parquet", "pdf"]
```

The file formats of an export.

### `BUCKETS`

```gizlang
const BUCKETS = 4096
```

The most buckets of a reduction on one axis.

### `AGGREGATES`

```gizlang
const AGGREGATES = ["count", "distinct", "sum", "avg", "min", "max", "median", "p25", "p75", "p90", "p95", "p99", "stddev", "variance"]
```

The aggregates of a measure. `median` and `pNN` are nearest-rank quantiles; `stddev` and `variance` are of a sample.

### `COMPUTED`

```gizlang
const COMPUTED = 16
```

The most calculated columns of one Spec, and the longest expression.

### `CUBE_CELLS`

```gizlang
const CUBE_CELLS = 50000
```

The most cells of a cube: a brush of more is refused, and the chart asks the server when the brush rests. Below the rows a text
source answers (gizdb:source TEXT_ROWS); a chart sizes the steps of its cube to its groups (giz-grid.js cubeOf).

### `NOTE_CHARS`

```gizlang
const NOTE_CHARS = 10000
```

The most characters of one note.

