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

# Using Functions in Query Builder

> Add SQL functions to output columns, filters, and join conditions without writing NQL

Query Builder lets you add functions to any expression — output columns, filter operands, and join conditions — without dropping into raw NQL. Each function is a first-class, type-safe node: Query Builder validates the argument types, constrains the picker to functions whose return type fits the slot, and round-trips both directions between the visual builder and the NQL tab.

## Prerequisites

* A Narrative I/O account
* Familiarity with [Query Builder basics](/getting-started/first-nql-query)
* Optional: a working knowledge of [NQL functions](/nql/functions) if you want to compare the visual output to the compiled SQL

## Available functions

Query Builder currently ships with a hard-coded catalog of 19 functions covering strings, math, logic, timestamps, and JSON. Every function is available in every expression slot whose type constraint the function's return type satisfies.

| Category    | Functions                                                                                   |
| ----------- | ------------------------------------------------------------------------------------------- |
| String      | `UPPER`, `LOWER`, `concat`, `concat_ws`, `SUBSTRING`, `length`, `REPLACE`, `regexp_extract` |
| Numeric     | `ROUND`, `ABS`, `CEIL`, `FLOOR`, `greatest`                                                 |
| Conditional | `COALESCE`                                                                                  |
| Date & time | `date_trunc`, `to_timestamp`                                                                |
| JSON        | `to_json`, `parse_json`, `object_remove_nulls`                                              |

<Note>
  Function names use the casing the NQL engine expects. Standard SQL builtins are uppercase (Calcite normalizes them); Spark-derived UDFs like `concat`, `regexp_extract`, and `date_trunc` are lowercase. See the [NQL functions reference](/nql/functions) for the full function catalog.
</Note>

Functions the catalog doesn't recognize — for example `CAST`, `EXTRACT`, `TRIM`, and `CASE` — still work when written in the NQL tab, but Query Builder shows them as raw NQL passthroughs rather than structured nodes.

## Adding a function

Wherever you can edit an expression, Query Builder offers **Add function** alongside options like column reference and literal.

<Steps>
  <Step title="Open the expression editor">
    Open Query Builder and start editing an expression — for example, click **Add** under **Output** and then **Add field**, or click into a filter operand or join condition.
  </Step>

  <Step title="Choose Add function">
    In the expression type picker, choose **Add function**. Query Builder shows a searchable list of functions whose return type is valid for this slot.

    * Search by name or description
    * Toggle between compact and detail views to preview each function's arguments and return type
  </Step>

  <Step title="Fill in the arguments">
    Once you select a function, Query Builder renders one input row per argument. Each argument shows:

    * The argument name in purple monospace
    * A description tooltip explaining what the argument means
    * The expected type

    Fill each slot the same way you fill any other expression — pick a column, add a literal, or nest another function.
  </Step>

  <Step title="Name function outputs">
    Function outputs require an alias. When you add a function to an **Output** column, the Add or Save button stays disabled until you provide a name — NQL needs an alias to project a computed column. Enter a name in the rename control that appears above the editor.
  </Step>
</Steps>

## How arguments behave

### Literal-first parameters

Some arguments are configuration values, not data. Query Builder opens these in **literal mode**: a bare, type-constrained input instead of the full expression picker. For example:

* `SUBSTRING` — `start` and `length` open as number inputs
* `ROUND` — `digits` opens as a number input
* `REPLACE` — `search` and `replacement` open as string inputs
* `regexp_extract` — `pattern` and `group` open as string and number inputs
* `concat_ws` — the leading `separator` opens as a string input

If you need a column reference or another expression in a literal-first slot, click the wrench icon next to the input to switch that slot to full expression mode. The wrench is a per-slot escape hatch — other arguments stay in literal mode.

<Tip>
  Pasting a non-literal expression into a literal-first slot automatically switches it to expression mode. Mode is derived from the argument node, not stored separately, so round-trips through the NQL tab preserve the argument exactly.
</Tip>

### Enum arguments

Arguments with a closed set of accepted values render as a select. `date_trunc`'s `unit` argument, for example, offers only `year`, `month`, `week`, `day`, `hour`, and `minute` — the engine rejects anything else.

### Variadic arguments

Functions like `concat`, `concat_ws`, `greatest`, and `COALESCE` accept a variable number of arguments. Query Builder shows one row per current argument plus an add-row control to grow the call. Argument names are numbered — `concat_ws` renders as `separator`, `value 1`, `value 2`, and so on.

## Type inference

Query Builder infers types across a function call so the picker only offers compatible functions and the arguments only accept compatible expressions.

**Outer to inner.** The slot's type constraint flows into the function's arguments. If a slot expects a string, `COALESCE` inside that slot only accepts string-typed operands. Functions with `matches_input` return types (like `COALESCE`, `greatest`, `ROUND`, and `ABS`) inherit the outer constraint.

**Sibling to sibling.** When there is no outer constraint — for example, in the Output step — the first filled argument of a `matches_input` function constrains the remaining `any`-typed slots. Filling one operand of `greatest` with a `long` column narrows the rest to numeric operands so the query doesn't fail inside the engine.

**Nesting.** A function's inferred return type feeds into any outer expression, so nesting `UPPER(concat(...))` in a string filter operand type-checks end to end.

## Editing and round-tripping

* **Rename.** Click the alias on a function output to rename it inline.
* **Swap the function.** Click the function name in the card header to reopen the picker. Query Builder preserves compatible arguments across the swap.
* **Convert to NQL.** Open the NQL tab to see the compiled SQL. Editing the NQL and returning to Query Builder re-parses aliased, whitespace-varied standard calls back into structured function nodes.
* **Special syntax.** Functions with special SQL syntax — `CAST(x AS type)`, `EXTRACT(field FROM x)`, `TRIM(BOTH ... FROM x)`, `CASE` — stay as raw NQL passthroughs when parsed back in. Edit them in the NQL tab.

## Related pages

<CardGroup cols={2}>
  <Card title="Write your first query" icon="terminal" href="/getting-started/first-nql-query">
    Walk through building a dataset in Query Builder end to end
  </Card>

  <Card title="Filtering and transforming" icon="filter" href="/guides/nql/filtering-transforming">
    Use expressions and functions in the NQL tab
  </Card>

  <Card title="NQL functions reference" icon="code" href="/nql/functions">
    Complete list of functions supported by the NQL engine
  </Card>

  <Card title="Using query templates" icon="file-code" href="/guides/nql/using-query-templates">
    Build reusable queries with configurable placeholders
  </Card>
</CardGroup>
