This page describes Calíope 1.5, the version we are building right now. 1.4 is finished and in App Review, and the store serves 1.3 on the Mac and 1.2 on iPad. The changelog says which version each feature landed in.

Adds an “Open in Calíope” button to every topic. It only works with the app installed.

Reports

A saved query with a defined output and declared parameters.

Where it is: Workspace › Tools › Reports

A report is not a snippet. A snippet is text you paste into the editor; a report is an artefact you run: it stores the columns it expects, how they are presented, which parameters it asks for and which source it comes from.

That is why running it twice gives the same thing, and why when what arrives doesn’t match what was declared you are told at the top instead of being shown a different table in silence.

It works with relational databases, with SQLite files and with MongoDB.

Keywords: report, saved query, output

Preparing before reading

A report may be several statements, as long as the last one is the SELECT that produces the table.

Where it is: Workspace › Tools › Reports

Not every report comes out of a single query. You can set a session variable, build a temporary table in several passes, index it, and read it at the end. The whole script runs on one connection, so the temporary table created in the first statement still exists in the last.

What you may use before the final SELECT: SET and USE for the session, CREATE TEMPORARY TABLE, and writing into tables this same report created — INSERT, UPDATE, DELETE, indexes, ALTER. Reads in the middle are allowed too.

What you may not: writing into a real table, CREATE TABLE without TEMPORARY, SET GLOBAL, PREPARE, EXECUTE and CALL. It is a closed list and anything outside it is rejected, with the statement number, before anything runs.

The reason is a promise: a report never touches your data. That is what makes it safe to schedule one at three in the morning.

Keywords: batch, temporary table, several statements, script, preparation

Parameters

Declared with a type and a default, and they travel apart from the query.

Where it is: Reports › Declare parameters

They are declared under “Declare parameters”, in the tool’s toolbar: each one with its name, its type, whether it is required and the value it arrives with. In the text they are written as “:name” in SQL and as "$$name" in MongoDB’s JSON.

Writing them in the text does not declare them. That is not the way: an undeclared marker makes the report fail validation. What the sheet does do is offer you the ones the query already uses, so you can declare them with the exact name.

A parameter is a value, not a piece of query. It is never pasted into the text: it travels bound separately, so nothing you type there can break the query or change what it does.

The trade-off is that you cannot parameterise a table name, nor a variable-length IN(…) list with a single marker. For the list there is the “list” type, which expands as many markers as values; for the table name there is no support, and that is deliberate.

Keywords: parameter, binding, injection, list

The defined output

Which columns show, in what order, with what title and what format.

Where it is: Reports › Output

This is what turns a saved query into a report. You can hide columns, reorder them, give them your own title, choose the format (thousands, two decimals, percentage, currency, date, bytes) and their alignment.

At the foot you can add per-column aggregates: sum, average, minimum, maximum and count. Nulls don’t count: an average divides by the values present, not by the rows.

The order you choose here is presentation and does not rewrite your query.

Keywords: columns, format, aggregate, chart

Exporting

CSV, TSV, JSON, Markdown, HTML, XML, text, Excel and a paginated PDF.

Where it is: Reports › Export

What gets exported is what the output declares: the visible columns, in their order, with their titles and formats. A PDF saying “Amount” and a CSV saying “total_eur” would not be the same report.

The PDF is paginated, with the header repeated on every page and its numbering; aggregates and notices go on the last one.

Everything goes through the system’s save panel: Calíope never writes to a folder you didn’t pick.

Keywords: export, pdf, excel, csv, share

Scheduling a report

Daily, weekly, weekdays, monthly or every N hours — with a limit worth knowing.

Where it is: Reports › Schedule

Scheduled runs only happen while Calíope is open. There is no background service, no daemon, no launch agent: on the Mac it runs with the app open, and on iPad, only in the foreground — no background window is ever granted to a report.

If the app is closed at the appointed time, the run is recorded in the history as skipped, with its reason, and retried at the next one. Missed runs are never fired all at once.

With nobody watching, each parameter’s default is used. A required parameter without a value is never invented: the run is recorded as skipped.

Keywords: schedule, automatic, skipped

Run history

What ran, when, with which values and on which machine.

Where it is: Reports › History

Every run leaves its row: whatever happens, including cancelled and skipped ones. It stores which parameters it ran with, how many rows it returned, how long it took, which machine ran it and —when there are two possible addresses— which one it connected through.

Reports and backups share the same history with two watertight scopes: from Reports you never see a single backup row, and vice versa.

You choose the retention, and it can be mirrored to iCloud so you can see it from your phone.

If the history itself couldn’t be written —a full disk, say— the footer says so: rows are missing then, and what you see isn’t everything that ran.

Keywords: history, runs, retention, audit