Skip to content

Compare with a Database Table or Cloud Object

Analyse → Compare with database or cloud... diffs the table you have open against a table on a saved database connection, or against an object in cloud storage.

This is the question you have after a load: did what I sent actually land? Until now answering it meant exporting the other side to a file first and diffing the two files.

What it does

Rows are matched on the key columns you pick, the way a join would, and the result opens in a detached tab in the standard compare shape:

Column Meaning
status only_in_a, only_in_b, changed_a, changed_b
changed_columns Which columns differ, for the changed pairs
(data columns) The row itself

"A" is your open tab, "B" is the database table. So only_in_a is in your file but not the warehouse, and only_in_b is the other way round.

There is no new comparison logic here: this is the same compare_join engine behind --diff --diff-mode join, given a database for one side instead of a file.

Comparing against a cloud object

Set Compare against to Cloud object and paste the object's URL:

Provider URL form
Amazon S3, MinIO, R2 s3://bucket/key.parquet
Azure Blob Storage az://container/blob
Google Cloud Storage gs://bucket/key
SFTP server sftp://user@host/path/key.csv
WebDAV / Nextcloud davs://host/path/key.csv

The object is downloaded to a temporary file and read like any local file, so every format Octa opens works here. Credentials come from a saved cloud connection covering the URL, otherwise from your ambient cloud login (AWS_* environment variables, a cached SSO session, az login, or Google application default credentials).

The same URLs work on the command line, where a cloud URL is accepted anywhere a file is:

octa --diff local.parquet s3://bucket/exports/day.parquet \
     --diff-mode join --diff-on customer_id

Using it

  1. Open the file you want to check.
  2. Analyse → Compare with database or cloud...
  3. Pick the connection, then fill in schema and table. Leave Catalog empty unless the connection is Snowflake, Databricks or BigQuery. An empty schema uses the connection's own database.
  4. Tick the key columns that identify a row. The Compare button stays disabled until you have named a table and at least one key, and its tooltip says which is missing.

The read runs on a worker thread, so the window stays responsive while a slow connection answers.

Tolerance

Open Tolerance under the key columns to count values as the same when they are close enough, or to leave columns out of the comparison.

  • Numbers within: two numbers count as the same when they differ by at most the absolute amount you type (for example 0.01), or by at most the percentage you type of the larger one. Either is enough. Both decimal marks work. Empty means exact.
  • Times within: dates and times count as the same when they are at most this many seconds apart. A date counts as midnight.
  • Ignore upper/lower case and Ignore extra spaces: text compares without regard to case, or with spaces at the ends removed and runs of spaces counted as one. These also apply when rows are matched on the key columns.
  • Leave out these columns: ticked columns are not compared, but they still appear in the result.

Tolerance never pairs keys: a number tolerance does not make key 1.0 match key 1.001. When some cells differ only within tolerance, the banner of the result tab says "N cells differ only within tolerance".

Command line

octa --diff orders.csv \
     --diff-db warehouse --diff-db-table public.orders \
     --diff-mode join --diff-on id

--diff-db names a saved connection, so a single file is the whole positional input. Output is the same compare table, on stdout:

status     changed_columns  id  city      amount
only_in_a                   3   Tokyo     30
only_in_b                   4   Cologne   40
changed_a  amount           2   Helsinki  20
changed_b  amount           2   Helsinki  99
mode join - unchanged: 1 - changed: 1 - only in A: 1 - only in B: 1

Columns are aligned here for readability; the real output is tab-separated (or CSV / JSON with -f), and the summary line goes to standard error so a pipe carries only the table. The blank changed_columns cells are the rows that exist on one side only.

That makes it usable as a load check in a pipeline.

MCP and the assistant

diff_tables takes a b_db object instead of path_b:

{
  "path_a": "orders.csv",
  "b_db": { "connection": "warehouse", "table": "public.orders" },
  "mode": "join",
  "on": ["id"]
}

Ceilings

  • Only loaded rows are compared. Both sides are read under the usual row cap, so on a large table the comparison covers its first rows. The result tab says so in a banner when either side hit the cap; raise the cap in Settings if you need the whole thing.
  • The comparison is a snapshot. Nothing locks the table, so rows written while the read is in flight may or may not appear.
  • Either side can be a database, so table-versus-table across two connections works the same way from the CLI.