Skip to main content
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
  • Optional: a working knowledge of 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.
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 for the full function catalog.
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.
1

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.
2

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
3

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.
4

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.

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:
  • SUBSTRINGstart and length open as number inputs
  • ROUNDdigits opens as a number input
  • REPLACEsearch and replacement open as string inputs
  • regexp_extractpattern 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.
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.

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.

Write your first query

Walk through building a dataset in Query Builder end to end

Filtering and transforming

Use expressions and functions in the NQL tab

NQL functions reference

Complete list of functions supported by the NQL engine

Using query templates

Build reusable queries with configurable placeholders