Docs · Concepts
Data sources
One query against one connection — the types available, running one across many machines, and what a run keeps.
A data source is one query against one connection. It belongs to exactly one Check. A Check with one source can only be a flat report; a comparison needs at least two.
#What you can connect to
Sixteen drivers, grouped in the add menu the way you would look for them.
Services
| API | REST, with parameters, auth, headers, body and an extract step |
Files
| File | CSV, JSON, XML, Excel |
Databases
| Default port | |
|---|---|
| PostgreSQL | 5432 |
| MySQL | 3306 |
| MariaDB | 3306 |
| Microsoft SQL Server | 1433 |
| Azure SQL Database | 1433 |
| Oracle | 1521 |
| SQLite | — |
| CockroachDB | 26257 |
Warehouses
| Default port | |
|---|---|
| Amazon Redshift | 5439 |
| Amazon Aurora MySQL | 3306 |
| Greenplum | 5432 |
| ClickHouse | 8123 |
| Vertica | 5433 |
| Snowflake | — |
Not relational
| Default port | |
|---|---|
| MongoDB | 27017 |
Kept in Mosaic
| Single value | One value, written in the editor |
| List of values | One per line |
| Table | Columns and rows, written or pasted in the editor |
Several of these share a driver with another product — MariaDB runs on the MySQL driver, Redshift and Greenplum on the PostgreSQL one — and the menu says so on the entry rather than hiding it.
The catalogue also lists eight products it cannot reach, each with the reason: Apache Cassandra, IBM Db2 LUW, H2, HSQLDB, Apache Derby, Exasol, Sybase ASE and Apache Hive. They are shown rather than omitted so you do not go looking.
#The editor
What you see depends on the driver.
| Driver | Tabs |
|---|---|
| API | Params · Auth · Headers · Body · Extract · Settings |
| SQL | Connection · Query · Binds · Settings |
| File | Source |
| Kept in Mosaic | Data |
Normalise and Result are added where they apply.
#Data kept in Mosaic
Some of what a Check needs is in no system at all: a mapping of tax codes, the list of stores in a pilot, a target figure finance agreed by email. Kept in Mosaic sources hold it with the source, written in its Data tab.
A table has a name and a Read as type for each column (text, number, date, yes / no), and is filled like a spreadsheet: Tab moves along a row, Enter down a column. Paste cells from a spreadsheet into any cell to fill the table from there, or into a column name to bring the headings too. A list takes one value per line, and a column copied from a spreadsheet pastes as one value per cell.
The cell being edited has a small square in its corner. Drag it down to copy the value to the rows below, or double-click it to copy the value to every row below.
From Business Locations starts a table from the places the workspace keeps: write which places ($Country = Italy), choose the level that gets a row (the stores, usually) and the columns to bring, such as the code, the name or a property. On a table that already holds values, the columns are added in front of what is there, or the table is replaced. The rows are a copy: a place added to Business Locations later is not added to the table.
Each run reads the cells into their column's type. A blank cell is empty, not 0. A number accepts a decimal comma as well as a point. A cell that does not read as its type is kept as written, so it shows up in the result where it can be seen.
#Using a kept table inside a query
A SQL query can read a table kept in Mosaic as if the database had it:
SELECT AN.STORE, AN.NAZCLI, CI.VAT_CODE
FROM SALES AN
INNER JOIN {{source:Vat Mapping}} CI ON AN.NAZCLI = CI.NAZCLI{{source:Name}} names a source of the same Check, spaces and all. Just before the query is sent, the token becomes the table's rows written out as a derived table, so whatever follows the token is its alias, as after a real table. Nothing is created on the database: no temporary table and no insert, nothing a read-only login could not run.
A table read this way holds at most 500 rows. A mapping of codes is tens of rows; a table bigger than that is data, and belongs beside the query in an aggregation rather than inside it. The query editor offers the Check's kept tables as you type, and changing one drops the cached rows of every query that names it.
#Running one against many machines
A SQL source can run the same query against more machines. The panel is called Collection, and each entry replaces the server named above it — port, database, credentials and query stay shared. Rows come back carrying a _source column naming the host they came from.
There are three places that list can come from:
- Own list — kept on the source itself.
- Library collection — shared. Edit the list once and every data source using it follows.
- Business Locations — the hosts are read from a property on your places, re-read at every run. See Business Locations.
Oracle needs an Easy Connect string for this, not a TNS alias.
Each host reports its own outcome — answered, unreachable or failed, with a row count — and the run log has a Hosts tab showing them. A probe reports partial success honestly: "Connected in 340 ms — 2 of 20 hosts unreachable".
#What happens when a source runs
Four steps, in this order:
- Parameter values are substituted, including any recode for this particular source.
- The driver runs the query, fanning out across the collection if there is one.
- Normalise transforms are applied — after the fan-out, so a twenty-host union is normalised as one result rather than per member.
- Row filters remove excluded rows, and the run always says how many it left out.
#Keeping a period from a service that cannot filter by date
Some services can only be asked for part of what you need. An order API that filters by store and status returns every order the store ever had, when the reconciliation is about one week. Row filters cut the period out after the rows arrive.
Add two rules on the date column:
| Column | Test | Value |
|---|---|---|
orderedDate | is before | {{dateFrom}} |
orderedDate | is after | {{dateTo}} |
Rows dated before the first day or after the last day are left out. Both days are kept. The value can be:
- a date, such as
2026-10-01,20261001or01/10/2026; - a day relative to today, such as
TODAY-7orSTART_OF_MONTH, worked out when the run happens; - a date parameter in double braces, which takes the value picked for the run.
Days are compared as written in the column. If the service writes timestamps in UTC and your days are local, add a Shift by hours transform on the column first: Normalise runs before the filters.
A row with no date is neither before nor after anything, so it is kept. Add an is blank rule if those should go too. A rule whose value is not a day, such as a parameter that does not exist, leaves nothing out, and the run says so.
The service still sends every row it has for the store and status, so the run takes as long as the full answer does. If the source's row limit cuts that answer short, the run warns you, and the rows you wanted may be among those not read. Raise the limit, or ask the service for less through the filters it does have.
#What is kept, and what is not
Kept: when it ran, whether it succeeded, how many rows, how long it took, any error — and the shape of what came back, so aggregations know which columns exist.
Not kept: the rows. They live in memory, capped across all sources, and are deliberately not persisted — rows can be large, they go stale, and the source of truth is always the upstream system.
This is why a source has to be run once before the column pickers downstream have anything to offer, and why they empty again after a restart until something runs.
The result pane offers Table, Raw, Schema, Headers, Request, Query and Pipeline, depending on the driver. The Request tab is worth knowing: it shows what Mosaic sent, captured before the call, with credentials redacted — so a connection that failed outright still tells you what it tried.
#The library
A data source can be kept in the library, outside any Check: "Connections and queries kept outside any check. Adding one to a check copies it — what the check holds is then its own."
That copy is the important part. Editing a library source does not change the Checks that took a copy of it. Collections and variables behave the other way round — they stay linked.