Skip to main content

Saved Queries

Use queries to sync reusable SQL queries and link them to a synced database.

Saved queries are synced as team-shared. CI has no personal user context, so every query pushed by the CLI is visible to the whole team in UIGraph.

Requirements

  • A service must be defined. Configs without a service may only sync maps and frames.
  • Each query's database must match a name under databases.
  • Each query provides its SQL through exactly one of queryText (inline) or path (external file).

Minimal config

databases:
- name: ecommerce
dialect: mysql
dbType: MySQL
schemaPath: ./ecommerce-schema.sql

queries:
- name: orphaned-orders
database: ecommerce
queryText: "SELECT * FROM orders WHERE customer_id IS NULL"
tags: [data-quality]

Query fields

Each item requires:

  • name — stable key used to upsert the query on repeat syncs
  • database — must match a databases[].name
  • exactly one of queryText or path

Optional:

  • description
  • tags — list of strings

name is the upsert key

name is the stable identifier the gateway uses to upsert a query. Rename it and the next sync creates a new query instead of updating the existing one in place.

queryText vs path

Provide the SQL one of two ways — exactly one is required:

  • queryText — inline SQL string
  • path — path to a .sql file, read as raw content at sync time
queries:
- name: top-customers-by-revenue
database: ecommerce
path: .uigraph/queries/top-customers-by-revenue.sql
description: Top 20 customers by lifetime revenue, last 90 days
tags: [reporting, revenue]

- name: daily-order-volume
database: ecommerce
queryText: "SELECT DATE(created_at) AS day, COUNT(*) AS orders FROM orders GROUP BY day ORDER BY day DESC"
description: Order count per day
tags: [reporting]

External query files

Use queryFiles to keep query definitions in separate files instead of inline in .uigraph.yaml. Each listed file contains its own queries: list.

Inline queries and external queryFiles may be used together — the entries are merged.

.uigraph.yaml:

queries:
- name: orphaned-orders
database: ecommerce
queryText: "SELECT * FROM orders WHERE customer_id IS NULL"
tags: [data-quality]

queryFiles:
- .uigraph/queries/reporting.yaml

.uigraph/queries/reporting.yaml:

queries:
- name: top-customers-by-revenue
database: ecommerce
path: .uigraph/queries/top-customers-by-revenue.sql
description: Top 20 customers by lifetime revenue, last 90 days
tags: [reporting, revenue]
- name: daily-order-volume
database: ecommerce
queryText: "SELECT DATE(created_at) AS day, COUNT(*) AS orders FROM orders GROUP BY day ORDER BY day DESC"
description: Order count per day
tags: [reporting]

All paths — including each query's path — are resolved relative to the working directory where the CLI runs, not relative to the file that references them.

What the CLI does

For each query (inline and from queryFiles), the CLI:

  1. validates that database matches a defined database
  2. validates that exactly one of path or queryText is set
  3. reads the SQL from queryText, or from path if a file is used
  4. sends the query text, metadata, and commit hash to the gateway

Queries are synced after database schemas, so a database referenced by a query is already present when the query is upserted.

  • keep .sql files in version control and reference them with path for anything non-trivial
  • use short inline queryText only for one-line checks
  • keep name stable so repeat syncs update in place rather than creating duplicates
  • group related queries into a queryFiles file per domain (e.g. reporting.yaml, data-quality.yaml)