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.

SQL Editor

Run a SQL query

Write and execute SQL against the connected server.

Where it is: SQL Editor › Run (⌘↩)

Type your SQL statement in the text editor. Press Run (play icon) or use the shortcut ⌘↩ to execute. If text is selected, only the selection is executed.

Results appear in the bottom table with rows and columns. Execution time and row count are shown in the status bar.

Keywords: run, execute, query, results, play

Stop a running query

Cuts the statement that is taking too long with KILL QUERY, without closing the connection.

Where it is: SQL Editor › Stop

The Stop button appears in the SQL Editor bar while an execution is under way, next to Run. On macOS it also answers to ⌘. (Command + period).

What it actually does. MySQL and MariaDB cannot abort a query over the same connection that is waiting for it, so Calíope opens another one and sends KILL QUERY <id> against the session running it. It is the same operation the Processes tool offers, aimed automatically at your own query.

- It uses KILL QUERY and not KILL CONNECTION: the statement is aborted and the connection stays alive, so there is nothing to reconnect, the open transaction is not lost, and the session's temporary tables do not disappear.
- In a script with several statements, the one running is stopped and the remaining ones are never sent.
- No special privileges are needed: any user can stop their own queries.
- When it is over, the status bar reads Query stopped. The Query execution was interrupted error the server returns is not shown as a failure: it is the expected answer.

Limits. The server decides when it can honour the request: a long SELECT is cut almost immediately, but an operation already inside the storage engine —an ALTER TABLE copying the table, a rollback under way— may take a while to let go, or may not let go at all. If that happens the statement is still alive on the server even though the app has stopped waiting for it: the Processes tool shows it.

Available on macOS, iPad and iPhone.

Keywords: stop, cancel, kill, kill query, abort, interrupt, slow query, hung, ⌘., detener

Clear editor and results

Clears the editor content and the results table.

Where it is: SQL Editor › Clear

Press the Clear button in the SQL Editor toolbar to erase both the editor text and the displayed results. The query history is not affected.

Keywords: clear, erase, clean editor, empty, reset

Format SQL (Beautify)

Applies indentation and readable formatting to the SQL in the editor.

Where it is: SQL Editor › Beautify (⌘L)

The Beautify button (or shortcut ⌘L) reformats the editor's SQL with uppercase keywords, correct indentation, and line breaks at clauses. Useful for reading compact or auto-generated scripts.

Keywords: format, beautify, pretty print, indent, uppercase

Curly quotes that break a query

Why the “Fix” notice appears under the editor, and what it does.

Where it is: Workspace › Tools › SQL Editor

SQL only understands straight quotes: ' for strings and " for identifiers in some modes. Curly quotes —‘ ’ “ ” « » „ “— are different characters, and the server rejects the statement with a syntax error even though it looks right on screen: in a monospaced font, ' and ‘ are very hard to tell apart.

Calíope never writes them. They show up when you paste SQL from Notes, mail or a chat, which do substitute quotes as you type. Inside the app the substitution is turned off in every editor, so whatever you type here always comes out straight.

When the editor spots one of these quotes where SQL expects a delimiter, a notice appears with a “Fix” button. It only changes the ones that can't be anything else: a curly quote inside a string is a valid character of your data —as in 'd’Artagnan'— and is left alone. If it isn't clear which one is wrong, nothing is changed and no notice appears.

Keywords: quotes, quote, curly, smart quotes, straight, apostrophe, syntax error, 1064, paste, fix

Safe mode

Blocks destructive statements to prevent mistakes. Enabled by default.

Where it is: SQL Editor › Safe mode

Safe mode is enabled by default on macOS, iPad and iPhone. When active, Calíope intercepts ALTER, DROP, DELETE, UPDATE, and TRUNCATE statements and shows a confirmation alert before executing them.

Use the Safe mode toggle (lock icon) in the SQL Editor toolbar to enable or disable it. The state is persisted per connection profile between sessions.

Useful when working in production or for users learning SQL who want protection against accidental changes.

Keywords: safe mode, lock, protect, drop, delete, default, destructive

Transactions

Manage BEGIN, COMMIT, and ROLLBACK from the transactions dropdown menu.

Where it is: SQL Editor › Transactions menu

The Transactions dropdown menu in the SQL Editor toolbar groups the three control operations: BEGIN (starts the transaction), COMMIT (confirms changes), and ROLLBACK (undoes changes).

COMMIT and ROLLBACK show a confirmation dialog before executing to prevent accidental changes. While a transaction is active, the results bar displays the Active Transaction label in green.

MySQL and MariaDB require the InnoDB table engine for full transaction support.

Keywords: transaction, commit, rollback, begin, InnoDB, dropdown

Query history

Access previously executed queries.

Where it is: SQL Editor › History

The History button (clock icon) opens a sheet with the queries you have already run: each row carries a green or red mark for how it ended, how long it took, and when. You can search them and load one back into the editor with the Use button.

One entry is recorded per execution, not per statement: if you fire a batch of twelve statements with Run Script, history stores the whole text as a single entry. To see it statement by statement, use the Statements button.

The sheet lists only the history of the active tab, and Clear wipes only that tab's. The / buttons beside it, by contrast, walk the entire history.

History is kept across sessions per connection profile (maximum 500 entries per profile), under the caliope_query_history_<profile id> UserDefaults key. What is not kept is the text of a run over 32 KB: that entry shows for the rest of the session and never reaches disk, because storing half of it would leave a truncated SQL in history that you can run again.

Keywords: history, previous queries, recent, log

Visual EXPLAIN

Visualize the execution plan of a SELECT query.

Where it is: SQL Editor › Visual EXPLAIN

With a SELECT statement in the editor, press the Visual EXPLAIN button. Calíope runs EXPLAIN FORMAT=JSON (MySQL/MariaDB syntax) and opens the result in the Visual EXPLAIN tab, which shows the plan node tree color-coded by access type.

Keywords: explain, plan, optimizer, index, full scan, execution plan

Statement delimiter

Choose the character that separates multiple statements before executing them.

Where it is: SQL Editor › Delimiter selector

The Delim selector in the results bar controls how Calíope splits the editor text into individual statements before executing. There are three preset options:

- ; (semicolon) — standard MySQL separator. Suitable for most queries.
- | (pipe) — useful alternative when the SQL contains semicolons inside string literals.
- $$ — common convention for writing stored procedures, functions, and triggers whose body contains ; internally. With this delimiter you can write CREATE PROCEDURE … BEGIN … END$$ blocks and Calíope will execute each block as a single statement.

On macOS you can also enter a custom delimiter in the text field next to the preset buttons.

The active delimiter is also used as a field separator when exporting results in CSV format.

The Statements panel splits on this same delimiter, so its list matches what will run. If you leave it empty, both the list and execution fall back to ;.

Keywords: delimiter, $$, pipe, semicolon, stored procedure, split, separator, CSV

Export results to file

Save query results in various formats.

Where it is: SQL Editor › Save result

Press the Save result button (floppy icon) in the results bar. Choose the output format — Table (text), JSON, CSV, HTML, or XML — and select where to save the file using the system save dialog.

The filename is pre-filled with the export date and time.

Keywords: export, save, csv, json, html, xml, file, download

Export table as INSERT

Generate INSERT statements for the current table or result set.

Where it is: SQL Editor › INSERT menu

The INSERT dropdown menu in the toolbar offers two options: Export result as INSERT (converts the rows of the current result) and Export table as INSERT (select a table from a dialog and export all its data).

The output is appended to the SQL editor as text ready to copy or execute.

Keywords: insert, export data, dump, seed, generate

Output formats

Change how query results are displayed.

Where it is: SQL Editor › Format selector

The Format selector in the results bar lets you choose between: Table (interactive grid), JSON (result as an array of objects), CSV (separated by the active Delim delimiter), Text (aligned columns), HTML (HTML table), and XML (per-field tags).

The selected format is also used when exporting the result to a file.

Keywords: format, table, json, csv, html, xml, output

Concatenate results

Accumulate results from multiple executions without clearing previous ones.

Where it is: SQL Editor › Concatenate

Enable the Concatenate toggle in the results bar. With this option active, each execution appends its rows to those already displayed instead of replacing them. Useful for combining results from similar queries run under different conditions.

Keywords: concatenate, accumulate, combine, append, multiple results

Auto-repeat (polling)

Automatically execute the query every N seconds.

Where it is: SQL Editor › Repeat

Enable the Repeat toggle and enter the interval in seconds. Calíope will execute the query automatically in a loop at that interval. Useful for monitoring the result of status or count queries in real time.

Disable the toggle to stop repeating.

Keywords: polling, repeat, auto-refresh, interval, monitor, loop

Link DB — connect a second database

Run each query simultaneously on two servers and compare the results.

Where it is: SQL Editor › Link database

The Link DB button (chain link with + icon) in the SQL Editor toolbar connects a second MySQL/MariaDB server to the active tab.

How to link:
1. Press Link DB. A picker appears with your recent connection profiles.
2. Choose the second server's profile and press Connect.
3. When the connection is established, the button is replaced by a green badge with the profile name and an button.

What happens when executing with a linked DB:
Every time you press Run or Run script, Calíope launches the same query on both servers in parallel (without blocking between them). Instead of the usual results table, the comparison view appears (see topic: Compare results between two servers).

Disconnect the linked DB:
Press the button on the green badge. The secondary connection closes, the comparison view disappears, and the editor returns to normal mode with the primary server's results.

Available on macOS, iPad and iPhone.

Keywords: link db, second server, secondary connection, parallel, compare, two servers

Compare results between two servers

Side-by-side comparison view with per-cell difference highlighting.

Where it is: SQL Editor › Link database

When a DB is linked (see Link DB), each execution shows the comparison view instead of the normal table.

Summary bar (top):
- Blue indicator — primary server name, row count, and execution time.
- Orange indicator — secondary server name, row count, and time.
- Result badge:
- ✓ Identical (green) — both results are exactly the same.
- ⚠ N value(s) · M extra row(s) (orange) — differences exist.
- "Diffs only" toggle — hides identical rows so you focus only on differences. Disabled when results are identical.

How to read the comparison table:
The table adds a DB column to the left of the data columns:

IndicatorMeaning
=Identical row on both servers (single row)
PRow from the primary server that differs from the secondary
SRow from the secondary server that differs from the primary

When a row differs, two consecutive rows (P and S) are shown. The exact cells where differences exist are highlighted:
- Soft red → value on the primary server that changed.
- Soft green → value on the secondary server that changed.

Rows that only exist on one server (count difference) appear with a blue background (primary only) or orange (secondary only).

Special states:
- Error on one or both servers — shows each server's error message separately.
- DML query (no columns) — shows rows affected by each server and whether they match.
- Mismatched columns — shows each server's column list with extra columns highlighted in orange.

Available on macOS, iPad and iPhone.

Keywords: compare, differences, diffs, two servers, parallel, highlight, identical, compare results, diffs only, badge, extra row

Insert snippet in the editor

Insert saved code fragments directly into the editor.

Where it is: SQL Editor › Snippets

Press the Snippets button (star icon) in the SQL Editor toolbar. A sheet opens with your saved snippets list: select one and press Insert to add it at the current cursor position in the editor.

Keywords: snippet, fragment, template, insert, code, reuse

View full cell value

View the complete content of cells with long text without expanding the row.

Where it is: SQL Editor › right-click › View full value

Result table cells display truncated text on a single line to keep rows compact. To read the full value without resizing columns:

macOS: Click any cell. A popover anchored to the cell appears with the full value, selectable, and with a Copy button at the bottom. The popover is scrollable if the content is very long.

iPad: Tap any cell. A sheet opens with the full value, selectable for partial copy. The sheet also has a Copy button in the top bar to copy all content.

On all three, the popover or sheet shows the column name in the header, and for long values (more than 50 characters) indicates the total character count.

Cells with a NULL value do not open the viewer when tapped.

Keywords: cell, full value, long text, popover, sheet, click, tap, truncated, read

Advanced cell edit

Edit cell values with a dedicated editor for long text, JSON, and binary data.

Where it is: SQL Editor › right-click › Advanced edit value…

Right-click (macOS) or long-press (iPad) any result cell and choose Edit advanced value… to open it in the Advanced cell editor. The editor has tabs for: plain text, JSON (with a format button), and binary/hex data.

Use the OK button to copy the edited value to the clipboard, or Load in editor if the cell contains SQL.

Keywords: cell, edit, json, blob, long text, context menu, advanced

Generate UPDATE from cell

Edit a cell's value and preview the UPDATE before executing it.

Where it is: SQL Editor › right-click › Generate UPDATE…

Calíope can generate and execute an UPDATE directly from any result cell.

macOS: Double-click a cell, or use right-click › Generate UPDATE…
iPad: Double-tap a cell, or long-press the cell and choose Generate UPDATE… from the context menu.

A panel opens with the following fields:

- New value — type the replacement value. Enable the NULL toggle to assign NULL.
- Table — automatically detected from your query's FROM clause. Edit it if needed (a ⚠ appears if not detected).
- WHERE column — the column acting as the primary key in the WHERE clause. Calíope prioritizes columns named id, then those ending in _id, and finally the first column.
- WHERE value — shows the current value of that column in the row. If it is NULL, an orange warning appears because the WHERE will affect all rows with that condition.

The generated SQL is editable — you can modify it before executing.

Press Execute UPDATE (macOS) or Execute (iPad) to run the statement. On success, the result shows rows affected and time, and the original query is automatically re-executed.

Keywords: update, edit cell, inline edit, generate sql, preview, where, pk, primary key, modify row

Delete row from results

Generate and execute a DELETE for the selected row with SQL preview and editing.

Where it is: SQL Editor › right-click › Delete row…

Calíope can generate a DELETE for any row visible in the results table.

macOS: Right-click any cell in the row and choose Delete row…
iPad: Long-press any cell in the row and choose Delete row… from the context menu.

A panel opens with the following fields:

- Table — automatically detected from your query's FROM clause. If the name is incorrect (e.g. when using JOINs or aliases), type it manually in database.table format.
- WHERE clause — choose the column acting as the primary key. Calíope prioritizes columns named id, then those ending in _id. Choose "Use all columns" to identify the row by all its values.
- Generated SQL — editable preview of the DELETE. Use the Copy SQL button to copy it to the clipboard without executing.

DELETE FROM `my_db`.`users`
  WHERE `id` = '42';

Press Delete row to execute. The original query is automatically re-executed to refresh the table. If an error occurs, the panel remains open and displays the server error message.

> Attention: Safe mode does not intercept this DELETE because it is executed internally, not from the editor. Always verify the WHERE before confirming.

Keywords: delete, delete row, context menu, results, table, where, copy sql, primary key

Contextual help for SQL functions

Consult the function documentation of the engine you are connected to without leaving the editor.

Where it is: SQL Editor › Text editor

Calíope shows built-in documentation for the SQL functions of the session's engine: with MySQL, MariaDB and Aurora, the ones of that family (SUM, DATE_FORMAT, JSON_EXTRACT, COALESCE, etc.); with PostgreSQL, its own (string_agg, to_char, jsonb_set, date_trunc, etc.). A name that exists in both does not share the entry, because it does not always mean the same thing: LENGTH counts characters in PostgreSQL and bytes in MySQL. If nothing appears when you hover over a function, it is because that function does not exist in the engine you are connected to.

macOS: Hover the cursor over the name of any recognized function in the editor. After a brief pause a popover appears with the syntax, return type, description, parameters with their types, and a usage example.

iPad: When the cursor is positioned inside or just after the name of a recognized function, a context bar automatically appears below the editor toolbar showing the name and syntax. Press the ? button in the bar to open the full documentation in a sheet.

The documentation includes:
- Complete function syntax
- Return type
- Description of behavior
- Parameters with name, type, and whether they are optional
- Example of use when available

Keywords: function, help, documentation, sum, count, date_format, json_extract, popover, autocomplete, mysql, mariadb, postgresql, to_char, string_agg

SQL statement manager

Analyze the editor script and manage its statements individually.

Where it is: SQL Editor › SQL Statements

The Statements button (list icon) opens the SQL Statement Manager, which splits the editor content by semicolon and shows each statement numbered, with its type (SELECT, INSERT, UPDATE, etc.) and a color icon. From the manager you can copy individual statements, load them into the editor, remove them from the list, or search among them.

It is a view of the text you have in the editor right now and executes nothing: it is recomputed every time you open the sheet, and Remove from list drops the row from the list, never from the editor. That is the difference from History, which records what has already run, one entry per execution.

The manager splits on the active delimiter from the results bar, the same one execution uses: with ; it splits on semicolons, and if you have set $$ to write a CREATE PROCEDURE, the whole block is listed as a single statement. So what it enumerates matches what will run.

Keywords: statements, split, manage, query list, script manager

Run complete script

Execute all editor statements at once with ⌘⇧↩.

Where it is: SQL Editor › Run script (⌘⇧↩)

Use the shortcut ⌘⇧↩ or the Run script button (double lightning icon) in the SQL Editor toolbar to execute all editor statements sequentially, regardless of whether text is selected.

macOS: the button appears next to the main Run button in the toolbar.
iPad: available in the editor's top toolbar.

Unlike Run (⌘↩), which only runs the active selection or the statement under the cursor, Run script processes all statements separated by the active delimiter in order and accumulates the results.

Keywords: run script, run all, ⌘⇧Return, all statements, full script, multiple queries

The results grid

Results come in pages: 50 rows on the Mac, 200 on iPad and iPhone.

Where it is: SQL Editor › Results grid

On macOS results come in pages of 50 rows, with their bar at the bottom —previous, next and a page indicator— which only appears when the query returned more than 50. You can sort by clicking a header, pick several rows with ⇧ or ⌘, copy them with ⌘C —they come out as TSV, with the column names on top— and drag them out of the app.

The sort is client-side, and it covers the whole result. It sorts the rows already fetched —all of them, not just the page in front of you— and the pages are cut afterwards. It does not sort the table on the server, and the grid says so underneath while a sort is applied. If you want the real top ten, the order goes in the query: ORDER BY … LIMIT 10.

The selection belongs to the page. It clears when you change page, so that ⌘C and dragging never carry rows that are no longer in front of you.

On iPad and iPhone the pages are 200 rows, with the same bar at the bottom.

On all three the split is local: the query runs in full and is divided in memory. If you need exactly a range of rows, add LIMIT and OFFSET to the query.

Keywords: grid, results, sort, header, select rows, copy, TSV, pagination, pages, 50 rows, 200 rows, LIMIT, OFFSET

Find and replace in the editor

Find and replace text in the SQL editor using the native system search.

Where it is: SQL Editor › Find (⌘F)

Press the Find button (magnifier icon) in the SQL Editor toolbar or use the shortcut ⌘F (macOS) to open the built-in search.

macOS: The native NSTextFinder is activated with search and replace fields, navigation between matches with / ⇧↩, and option to replace one or all matches.

iPad: UIFindInteraction is activated, presenting the native iOS search/replace bar above the keyboard with support for touch navigation between matches.

Keywords: find, replace, search, text, ⌘F, NSTextFinder

Navigate history from the editor (REPL style)

Retrieve previous queries directly from the editor without opening the history panel.

Where it is: SQL Editor › History ‹ › arrows

The SQL editor lets you recall previous queries straight from the text field, just like the mysql terminal.

macOS:
- Press with the cursor at the very start of the editor (position 0, nothing selected) to load the previous query from history.
- Press with the cursor on the last line to come back toward the present.
- You can also use the / buttons in the editor toolbar.

iPad:
- Use the / buttons, or ⌘↑ / ⌘↓ with a hardware keyboard.

Nothing is lost while navigating. Entering the history saves whatever was in the editor, and coming back with restores it as it was — you are not left with a blank editor. And if what you have is a half-written draft of your own, neither the keys nor the buttons touch it: and move the cursor as usual.

Keys and buttons share a single trip, so undoes exactly what did. What they walk is the history of the active tab, the same one listed by the sheet behind the History button. Navigating history does not modify it.

Keywords: history, REPL, arrow, navigate, up, down, previous, next, chevron

Pin results to compare

Save the current result to consult it while running other queries.

Where it is: SQL Editor › Pin result

The Pin button (pin icon) in the results bar saves a copy of the current result together with the SQL that generated it and the execution time. The pinned result persists even when other queries are executed.

When pinned results exist, the Pinned (N) button appears, toggling the visibility of the pinned results panel. Each pinned result shows:
- The abbreviated SQL that generated it
- The number of rows and columns
- The execution time
- An button to unpin that result individually

Available on macOS, iPad and iPhone. Useful for comparing the state of a table before and after a change.

Keywords: pin, pinned results, compare, multiple, save result, before and after

Integrated SQL terminal (REPL mode)

Terminal-style panel with mysql> prompt for interactive SQL execution.

Where it is: SQL Editor › Terminal

The Terminal button (terminal icon) in the SQL Editor toolbar opens a REPL-style bottom panel.

How to use it:
- Type SQL in the field with the mysql> prompt and press (or the ↵ button) to execute.
- SELECT results are shown as an ASCII table with +---+ separators.
- DML statements show "Query OK, N row(s) affected".
- Errors are shown in red with the MySQL message.

Navigate terminal history:
- macOS: Use / in the input field to scroll through previous terminal queries.
- iPad: Use the / buttons above the input field.

Clear: The trash button in the header clears the terminal output.

The terminal has its own history independent of the main SQL Editor. Queries executed from the terminal are also added to the session's global history.

Available on macOS, iPad and iPhone.

Keywords: terminal, REPL, prompt, mysql, interactive, console, ascii, table

Export results in multiple formats

Save results in JSON, Markdown, XML, or Excel (.xlsx) in addition to CSV.

Where it is: SQL Editor › Format selector

In addition to the classic formats (Table, CSV, HTML), the Format selector in the results bar includes:

- JSON — array of objects, ideal for APIs and development tools.
- Markdown — Markdown table format, ready to paste into documentation or Notion.
- XML — one element per row, compatible with data processing tools.
- Excel (.xlsx) — spreadsheet ready to open in Numbers or Excel. Use the Save button that appears in the results bar when selecting this format.

The Save / Share button in the results bar exports with the active format selected in the picker.

Available on macOS, iPad and iPhone.

Keywords: export, json, markdown, xml, excel, xlsx, format, save result, numbers

Expand SELECT * into explicit columns

Replace the asterisk in a SELECT with the actual column names of the table.

Where it is: SQL Editor › right-click › Expand * → columns

When you have a SELECT * FROM table in the editor, Calíope can expand that * to the explicit list of table columns directly in the editor.

How to use it (macOS):
1. Position the cursor inside the SELECT statement containing the *.
2. Right-click the editor to open the context menu.
3. Select Expand * → columns of table_name.

Calíope queries the server to get the table's current columns and replaces the * with the backtick-quoted column list separated by commas, for example:

SELECT `id`, `name`, `email`, `created_at` FROM `users`

Requirements:
- An active database must be selected in the toolbar selector.
- The option only appears in the context menu when the cursor is inside a valid SELECT … FROM table statement.
- The table must exist in the active database and the user must have read permissions.

Available on macOS only. Column expansion is not available on iPad or iPhone in this version.

Keywords: expand, asterisk, SELECT *, columns, explicit, expand, replace, backtick

Autocomplete in the SQL editor

Completes SQL keywords, table names, and column names. Automatic popup on typing requires enabling an option in Preferences.

Where it is: Calíope › Preferences › Text editor

The SQL editor offers two independent autocomplete layers.

1. SQL keywords:
The editor knows all MySQL/MariaDB keywords (SELECT, FROM, WHERE, JOIN, GROUP BY, etc.) and includes them in the suggestion popup. Enable or disable this layer in Preferences › Text editor › Autocomplete SQL keywords.

2. Table and column names from the schema:
Calíope loads the active database's objects (tables, columns, aliases) and adds them to the suggestions. You do not have to start at the beginning of the name: any part of it works, and the ones that start with what you typed come first.

---

How the popup opens:

- Manually: ⌘N on macOS, and on iPad the Autocomplete button in the editor toolbar — or ⌘N, if you have a physical keyboard. It opens the popup at any time, regardless of what you have typed. The button is there whenever autocomplete is enabled in Preferences, which is the same switch that governs the shortcut.

- Automatically while typing: the popup can appear on its own after you stop typing for a brief moment. This feature is disabled by default. To enable it, go to Preferences › Text editor and turn on the "Real-time autocomplete" toggle. Once active, the popup appears approximately 350 ms after the last keystroke.

If you type SEL, pause, and nothing appears, real-time autocomplete is not enabled. Use ⌘N — or the toolbar button, on iPad — to open it manually, or enable the option in Preferences.

---

Object popup when typing a dot:
If you type a database name in backticks followed by a dot (e.g. `my_db`. ), the editor automatically shows the tables in that database for direct selection. As you keep typing, the list narrows down to the names that contain what you wrote.

Available on macOS, iPad and iPhone. On iPad and iPhone you do not need a keyboard: the toolbar button opens the popup exactly like ⌘N.

Keywords: autocomplete, suggestions, keywords, tables, columns, popup, complete, ⌘N, real-time, live, debounce, automatic

Fold and unfold blocks in the editor

Collapse or expand parenthesis and BEGIN…END blocks to simplify reading complex scripts.

Where it is: Keyboard shortcut: ⌃. / ⌃, — clic en el margen izquierdo

The Calíope SQL editor allows folding (collapsing) two types of blocks:

1. Parenthesis blocks (…)
Useful for long subqueries, IN (…) clauses, or column lists in CREATE TABLE. The ▼ triangle appears in the left margin on any line containing a ( with inner line breaks.

2. BEGIN…END blocks
Stored procedure, function, trigger, and MariaDB/MySQL event bodies use BEGIN…END. The ▼ triangle appears in the left margin above the line containing BEGIN. When folded, the block appears as BEGIN(…)END, keeping the object signature visible (CREATE PROCEDURE …, CREATE FUNCTION …, etc.).

Supported blocks:
- CREATE PROCEDURE name() BEGIN … END
- CREATE FUNCTION name() RETURNS type BEGIN … END
- CREATE TRIGGER name … BEGIN … END
- CREATE EVENT name … DO BEGIN … END
- Standalone BEGIN … END blocks (transaction start)

END IF, END LOOP, END CASE, END WHILE, and similar blocks do not close a routine BEGIN and are correctly ignored.

How to fold/unfold:
- With mouse / touch: Click (macOS) or tap (iPad) the ▼ triangle in the left margin of the line.
- With keyboard (macOS):
- ⌃. (Control + period) — Folds the block (parenthesis or BEGIN…END) containing the cursor.
- ⌃, (Control + comma) — Unfolds the folded block at the cursor position.

Behavior:
- Folding is visual only: the full text remains in the editor and is sent entirely to the server on execution.
- Folds are preserved while the tab remains open.

Available on macOS, iPad and iPhone.

Keywords: fold, unfold, parenthesis, collapse, subquery, nested, ⌃., ⌃, BEGIN, END, procedure, stored function, trigger, routine, begin end, fold block

Performance monitor (CPU and memory)

Indicator in the sidebar showing app CPU and RAM, with cleanup suggestions when usage is high.

Where it is: Sidebar › Performance monitor (sidebar bottom)

The performance monitor appears at the bottom of the workspace's left sidebar (below the schema tree). It shows the current CPU and RAM usage of the Calíope app.

Indicator colors:
- 🟢 Green — Normal performance (CPU < 30%, RAM < 5% of total system RAM)
- 🟡 Amber — High usage (CPU 30–70% or RAM 5–10% of total system RAM)
- 🔴 Red — High pressure (CPU > 70% or RAM > 10% of total system RAM; on iPad also triggered by an OS alert)

What "Clear results" means: discards the current result row array for that SQL Editor tab, freeing the memory they occupy. The query written in the editor is not deleted; you can re-execute it at any time.

When to act: if the indicator badge appears in red, the app may respond more slowly. Press or tap the indicator to see the detail panel — the suggestions show exactly which tab is using the most memory and offer a direct action button.

Available on macOS, iPad and iPhone.

Keywords: performance, memory, cpu, ram, slow, clear results, monitor, pressure, high usage

Toggle SQL comment (⌘D)

Comment or uncomment selected lines with the '--' prefix.

Where it is: SQL Editor › Comment

Press ⌘D (or the Comment button in the toolbar) to toggle SQL comments on the selected lines.

Behavior:
- If text is selected, it acts on all lines within the selection.
- Without a selection, it acts on the line where the cursor is.
- If all non-empty lines already start with --, it uncomments them; otherwise it adds -- to the beginning of each line.

Shortcuts:
- macOS: ⌘D in the editor or button in the toolbar
- iPad: ⌘D with Magic Keyboard or button in the toolbar

The operation is undoable on macOS with ⌘Z.

Keywords: comment, toggle comment, uncomment, --, sql comment, cmd d, lines

Linting — error diagnosis before executing

Underlines lexical errors in the editor while you type, without executing anything against the database.

Where it is: SQL Editor › Results bar

Pre-execution linting analyzes the editor text automatically (500 ms after you stop typing) and underlines with a red dashed line the lexical errors that MySQL/MariaDB would definitively reject.

Detected errors:

ErrorExample
Unclosed string literalWHERE name = 'john
Unclosed backtick identifierSELECT `column
Unclosed block comment/* no close
Opening parenthesis without closeSIN(x + 1
Closing parenthesis without openSIN x + 1)

How to read it:
- The problematic character is underlined with a red dashed line.
- A red badge appears in the results bar with the number of errors (e.g. ⚠ 2 error(s)). Hovering over the badge shows all messages.
- If there are no errors the badge disappears.

Limitations:
The linter is purely lexical; it does not validate that table or column names exist on the server, nor does it check SQL clause semantics. Its purpose is to catch the most obvious errors — unclosed strings, unbalanced parentheses — which are often difficult to spot in long scripts.

Available on macOS, iPad and iPhone.

Keywords: lint, linting, error, diagnosis, underline, before executing, parenthesis, string, backtick, comment, pre-execution

Automatic line wrap (word wrap)

Control whether long lines wrap visually or allow horizontal scrolling.

Where it is: SQL Editor › Preferences → Editor

Word wrap determines how lines in the editor are displayed when their length exceeds the visible width.

Enabled (default): long lines wrap onto the next visual line without inserting any character in the text. More comfortable for reading complex queries without horizontal scrolling.

Disabled: each line occupies exactly one row. A horizontal scrollbar appears at the bottom of the editor so you can see the full line without interruption. Useful for scripts with tabular alignment (SELECT column1, column2, ...) or for reviewing auto-generated code with very long lines.

How to change it:
- macOS: menu Calíope → Preferences → Editor → Word wrap.
- iPad: app Settings → same option.

The setting is shared between macOS, iPad and iPhone via the caliope_pref_word_wrap UserDefaults key.

Keywords: word wrap, line wrap, wrap, horizontal scroll, long lines, preferences, settings, no wrap

Bracket pair highlighting

Illuminates the matching closing/opening bracket or keyword to the cursor.

Where it is: SQL Editor › Text editor

When the cursor is next to a bracket or the keywords BEGIN/END, the editor automatically highlights the character or keyword that matches it.

Supported pair types:

OpensClosesSQL Example
()subqueries, function calls
{}inline JSON
[]names with spaces [my table]
BEGINENDprocedures, functions, triggers, events

Color code:
- Yellow — both ends matched correctly.
- Red — the bracket or keyword has no pair (imbalance).

Behavior:
- Highlighting updates in real time as you move the cursor or modify the text.
- END IF, END LOOP, END CASE, END WHILE, END REPEAT, and END FOR are correctly ignored: only ENDs that close a routine BEGIN block are matched.
- Nested BEGIN/END blocks are resolved with depth counting (the correct END is identified even with multiple nesting levels).

Available on macOS, iPad and iPhone.

Keywords: bracket, parenthesis, matching, pair, highlight, BEGIN, END, brace, imbalance, nested, highlight pair

Highlight every match of a word

Double-click a word and the editor lights up all of its occurrences in the text.

Where it is: SQL Editor › Text editor

Double-click a word in the editor —a table name, a column, an alias, a keyword— and all of its other occurrences are painted with a teal background. On iPad the equivalent gesture is the double tap.

How it decides what to highlight:
- Matching is whole-word: selecting id does not light up the id inside identifier.
- It is case-insensitive, because to MySQL Id, id and ID are the same column.
- The selection must be exactly one word: if it spans spaces, commas or parentheses, or cuts a word in half, nothing is highlighted.
- The word must be at least two characters long.
- The selected word itself is not repainted: the selection colour already sets it apart.

The highlight goes away when the caret moves, when something else is selected, or when the text is edited. At most 500 occurrences are lit; in a script where that ceiling is reached, Find (⌘F) is the better tool, since it also walks from one to the next.

Available on macOS, iPad and iPhone.

Keywords: highlight, matches, double click, double tap, occurrences, word, select word, light up, resaltar

Column editing / multi-cursor

Edit simultaneously at multiple positions in the editor.

Where it is: SQL Editor › Column editing

Column editing mode places secondary cursors on several lines and types or deletes on all of them at once. It is what you want for renaming an alias on five rows, or adding a prefix or a suffix to a block of lines.

On macOS:
AppKit has no multi-cursor of its own, so Calíope draws it. Use the Column editing button in the toolbar, or just press ⌥⌘↓, which turns the mode on and puts the second cursor in one go; the button turns purple while it is on. From there, each click adds a cursor, and ⌥⌘↓ / ⌥⌘↑ add one on the line below or above without touching the mouse — the column is kept, and clipped to the end of a shorter line. Esc leaves the mode. Here ⌘⇧M is not the shortcut: on macOS it already opens the snippet picker.

On iPad:
Press ⌘⇧M with a Magic Keyboard or the Column editing button in the toolbar. With the mode active, each tap in the editor accumulates a secondary cursor.

On both, a secondary cursor is a blue vertical line with its row highlighted, and typing or deleting works the same way: the character goes first to the primary cursor, and is then replicated to the secondary positions from the highest index to the lowest, so that inserting at one does not move the ones still to come.

Available on macOS, iPad and iPhone.

Keywords: multi-cursor, column edit, cursors, ⌘⇧M, ⌥⌘↓, add cursor, simultaneous, column, multicursor

Go to Definition

Navigate from the editor directly to the definition of a table, view, routine, or trigger in the catalog.

Where it is: SQL Editor › right-click › Go to definition

Go to Definition resolves the identifier name under the cursor and opens the Catalogs tab showing that object selected.

How to activate it:

PlatformMethod
macOS⌘ + click on the identifier in the editor
macOSF12 with the cursor positioned on the identifier
macOSRight-click › Go to Definition in the context menu
iPadLong-press any identifier → context menu → Go to Definition

Recognized objects:
- Tables → opens the Catalogs tab and selects the table
- Views → switches to the Views tab and selects the view
- Procedures and functions → switches to the Routines tab
- Triggers → switches to the Triggers tab

Behavior:
1. Calíope queries the objects of the active database in the selector.
2. If the identifier matches a known object, it opens (or activates) the Catalogs tab and automatically selects the object — including loading the DDL in the bottom panel.
3. If the identifier does not exist in the active schema, the status bar shows "Object not found in schema" without opening the catalog.

Requirement: an active database must be selected in the toolbar selector.

Available on macOS, iPad and iPhone.

Keywords: go to definition, navigate, table, view, routine, catalog, F12, cmd click, long press, identifier, schema

DDL hover tooltip

Shows the DDL of tables, views, routines, and triggers just by hovering over their name in the editor.

Where it is: SQL Editor › DDL Tooltip

Hover DDL tooltip is the fastest way to inspect a schema object's definition without leaving the editor.

How it works:

PlatformBehavior
macOSHover the cursor over any schema object name for 0.4 s — a popover appears with the full DDL
iPadMove the text cursor (tap) over a schema identifier — the DDL bar appears below the toolbar

Without a pointer (macOS): Navigate › Function help at the cursor (⌃⌘?) opens the card for whatever is at the text cursor — the same popover the hover shows, including a function you have just typed (DATE_FORMAT(). If there is nothing to document there, you hear a beep.

Popover / DDL bar content:
- Icon and badge by type (TABLE, VIEW, PROCEDURE, FUNCTION, TRIGGER, EVENT)
- Full DDL in monospace font, with text selection enabled
- "Go to Definition" button → navigates to the object in the Catalogs tab

Recognized objects:
Tables · Views · Stored procedures · Functions · Triggers · Events

Coexistence with native function help:
- If the identifier is a native SQL function followed by ( (e.g. DATE_FORMAT(), the function documentation is shown, not the DDL.
- If the identifier is a schema object without ( following it, the DDL tooltip is shown.
- Both systems do not activate simultaneously.

Cache: each object's DDL is stored in memory during the session to avoid repeated queries.

Requirement: an active database must be selected in the toolbar selector.

Available on macOS, iPad and iPhone.

Keywords: ddl, hover, tooltip, popover, create table, show create, definition, table, view, procedure, function, trigger, event, inspection, schema, hint bar

Quick Open — Quick object access

Search palette to jump to any object in the active schema by typing part of its name.

Where it is: SQL Editor › Quick Open

Quick Open is an instant search palette that lets you navigate to any table, view, procedure, function, trigger, or event without leaving the editor or browsing the Catalogs tree.

How to open it:

PlatformMethod
macOS⌘⇧O (Navigate menu › Quick Open…)
iPad⌘⇧O (Magic Keyboard) or Quick Open button in the editor toolbar

How to use it:
1. A panel opens with a search field.
2. Type any part of the object name — the list filters in real time.
3. Select the result with ↑↓ keys and confirm with , or click directly on the item.
4. Calíope automatically navigates to the object in the Catalogs tab.
5. Press Esc at any time to close without navigating.

Search algorithm (fuzzy matching in three levels):
- The name starts with the typed text → highest priority
- The name contains the text at any position → medium priority
- The typed characters appear in order as a subsequence (e.g. cru finds create_user) → lowest priority

Matching results are highlighted in the app's accent color.

Recognized objects: tables · views · procedures · functions · triggers · events

Scope: searches only in the active database in the toolbar selector.

Available on macOS, iPad and iPhone.

Keywords: quick open, fuzzy, search object, palette, table, view, procedure, function, trigger, event, navigate, catalog, ⌘⇧O, schema

Rename symbol in script

Rename an alias, CTE, or variable and propagate the change to all its references in the active script.

Where it is: SQL Editor › right-click › Rename symbol

Rename symbol lets you change the name of any local identifier in the script — column alias, CTE name, variable — and automatically replace all its occurrences in the same file in a single operation.

How to invoke it?

PlatformAction
macOSRight-click the identifier → Rename symbol…
iPadLong-press the identifier → context menu → Rename symbol…

Type the new name in the dialog that appears and confirm with Rename (or press ↵). All occurrences are substituted in one step.

Undo: the entire operation is undone with a single ⌘Z (macOS) or by shaking the device / undo button (iPad). You don't need to undo occurrence by occurrence.

Scope: only the script open in the active tab. Does not modify any object in the database.

Matching: uses whole-word boundaries, so renaming id does not affect client_id or user_id.

Note: the replacement is case-sensitive and is applied to the full script text, including comments and string literals if the identifier appears in them.

Available on macOS, iPad and iPhone.

Keywords: rename, symbol, alias, cte, variable, refactoring, replace, identifier, script, whole word, context menu

Query Builder — Visual query constructor

Build SELECT queries visually by dragging tables, choosing columns, and letting Calíope auto-generate JOINs.

Where it is: Workspace › Query Builder

Query Builder is a workspace tab that lets you build SELECT queries visually, without writing SQL manually.

How to open it?

- macOS / iPad: Query Builder tab in the workspace navigation bar (grouped rectangles icon).

Workflow

1. The left panel shows all tables in the active database.
2. Press + next to a table (or drag it to the canvas on macOS) to add it.
3. Each table appears as a card with checkboxes per column. All columns are checked by default; uncheck the ones you don't need.
4. Calíope automatically detects foreign keys between the canvas tables and generates the corresponding JOIN.
5. If no FK exists between two tables, a CROSS JOIN is inserted with a warning comment.
6. The bottom panel shows the SQL generated in real time.
7. Press Insert into editor to open the SQL in a new editor tab.

Canvas options

ControlDescription
JOIN typeSwitch between INNER, LEFT, and RIGHT for all canvas JOINs
AliasTap a table alias (underlined blue letter) to edit it
Select all / noneIn the footer of each card
Clear canvasRemoves all tables from the canvas

Notes
- JOINs are detected via information_schema.KEY_COLUMN_USAGE (MySQL/MariaDB syntax). If the database has no declared FKs, a CROSS JOIN will appear that you must adjust manually in the editor.
- The generated SQL is a starting point; you can edit it freely once inserted.

Available on macOS, iPad and iPhone.

Conditions (WHERE)

Between the canvas and the SQL there is a collapsible Conditions section where you filter the query. Press Add condition and pick a column, an operator and a value.

DetailWhat it does
Operators=, !=, >, <, >=, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, IS NULL, IS NOT NULL. LIKE is not offered on numeric columns.
QuotingDecided by the column's declared type: a varchar is quoted even when the value looks like a number.
INComma-separated values. If a value contains a comma, wrap it in single quotes: 'Pérez, Ana', Luis.
{} buttonTreats the value as a SQL expression rather than a literal: another column (p.fecha) or a function (NOW()).
AND / ORThe connector is per row. When you mix them the SQL comes out with explicit parentheses, so the precedence is the one you read.

A half-filled condition does not break the query: it is flagged in the list and left out of the SQL.

Outer JOIN warning

With LEFT or RIGHT JOIN, filtering in the WHERE the side that can come out as NULL discards exactly the unmatched rows, and the JOIN ends up behaving like an INNER. When that happens the condition is flagged and Move to ON is offered, which moves it into the join condition and keeps the orphan rows. IS NULL raises no warning: that is the deliberate pattern for finding "the ones without".

The table panel has a filter by name in its header: in a database with many tables, type part of the name instead of scrolling until you find it. It is the same schema tree the rest of the app uses, scoped to the active database.

Keywords: query builder, visual, select, join, inner join, left join, foreign key, drag, canvas, tables, columns, query, generated sql, where, conditions, filter, operator, and, or, between, like, in, null, outer join, on

Editor minimap

Thumbnail view of the full script with current position indicator.

Where it is: SQL Editor › Preferences → Editor

The minimap shows a reduced visual representation of the entire editor content in the right margin. A semi-transparent blue band indicates which portion of the script is currently visible in the main area.

To enable it:
- macOS: menu Calíope → Preferences → Editor → Show minimap.
- iPad: app Settings → same option.

Navigation with the minimap:
- Click / tap anywhere on the minimap scrolls the editor to that position in the script.
- Drag over the minimap for continuous navigation.
- The minimap updates automatically when typing and when scrolling.

Visual representation:
Each line of the script appears as a horizontal bar whose width is proportional to the line length (normalized to 80 characters). The color corresponds to the editor text at low opacity; it does not replicate the syntax highlighting colors.

Dimensions:
- macOS: 80 pt wide in the right margin of the editor.
- iPad: 64 pt wide. The text area adjusts automatically to avoid being covered.

Available on macOS, iPad and iPhone.

Keywords: minimap, map, overview, navigation, full script, scroll, right margin, position

Open SQL files by dragging

Drag a .sql or .txt file directly onto the workspace to open it in a new editor tab.

Where it is: Workspace › SQL Editor

Open SQL files by dragging

You can open any .sql or .txt file by dragging it directly onto the Calíope workspace window, without using the menu or file selector.

How to do it on macOS:
1. Open Finder and locate your .sql file.
2. Drag the file onto the main area of the Calíope workspace.
3. A blue visual indicator appears while you hold the file over the area.
4. Drop the file — the content automatically opens in a new SQL editor tab.

How to do it on iPad:
1. Open the Files app in Split View or Stage Manager alongside Calíope.
2. Long-press the .sql file until it "lifts".
3. Drag it toward the Calíope workspace.
4. Drop it on the editor area — the content opens in a new tab.

Accepted formats:
- .sql files (any SQL script)
- .txt files containing SQL text

Other opening methods:
- File menu → Open SQL file… (shortcut: ⌃⌥O on macOS)
- Drag onto the Dock icon on macOS (handled by the system)
- Share → Open with Calíope from the Files app on iPad

Available on macOS, iPad and iPhone.

Keywords: drag, drop, sql file, open file, files app, finder, import script

Customize toolbars

Reorder button groups in the editor and results toolbars.

Where it is: SQL Editor › Customize (leftmost end of each bar)

Both SQL Editor toolbars — the editor toolbar (top) and the results toolbar (bottom) — can be customized to adapt button order to your workflow.

How to do it:
1. Press the Customize button (three sliders icon) that appears at the far left of each toolbar.
2. In the panel that opens, you will see the list of button groups in their current order.
3. Drag each row to reorder it as you prefer.
4. Press Done to save the changes.

The order is automatically saved and maintained between sessions. Use the Reset button to return to the default order.

The available groups in the editor toolbar are: Run, Code format, Security and transactions, History and navigation, SQL analysis, Tools, Performance, External connection, and Font size.

The available groups in the results toolbar are: Delimiter, Output format, Options, Font size, Save result, Pin results, and Query analysis.

Available on macOS, iPad and iPhone, with one order for the Mac and another shared by iPad and iPhone.

Keywords: customize, reorder, toolbar, order, groups, drag, buttons

Long query notification

Receive a system notification when a query exceeds the configured time threshold.

Where it is: Calíope › Preferences › Notifications

When you run a query that takes longer than expected and switch to another app while waiting, Calíope can send you a local notification when it finishes.

Configure the threshold:
Go to Preferences › Notifications and enable Long query completed. Adjust the threshold with the stepper (default 5 s; range 1–300 s).

The notification fires at most once per 60-second window to avoid spam. It also arrives with Calíope in the foreground: the only notices silenced while the app is in front are the two about manual backups.

Keywords: notification, long query, time, threshold, background, alert

Large result set notification

Get notified when a query returns more rows than the configured threshold.

Where it is: Calíope › Preferences › Notifications

If a query returns a very large number of rows, Calíope can alert you with a local notification.

Configure the threshold:
Go to Preferences › Notifications and enable Unusually large result set. Adjust the threshold with the stepper (default 10 000 rows; range 1 000–100 000).

Results are always displayed on screen; the notification is informational only.

Keywords: notification, large result, rows, threshold, volume, alert

Advanced Cell Editor (long text, JSON, binary)

Edit complex values in a dedicated sheet with tabs for text, JSON, and binary data.

Where it is: Results › right-click › Edit advanced value…

The Advanced Cell Editor is a modal sheet designed for values that don't fit comfortably in the grid: long texts (TEXT, MEDIUMTEXT, LONGTEXT), JSON documents, binary content (BLOB, VARBINARY), and strings with line breaks.

How to open it
- macOS: right-click on the cell and choose Edit advanced value…, or press ⌘E with the cell selected.
- iPad: long-press the cell and choose Edit advanced value… from the contextual menu.

Editor tabs
- Text — plain-text editing field with character and line counters and an optional word-wrap toggle. Useful for VARCHAR/TEXT with line breaks.
- JSON — editor with syntax coloring and validation. The Format button applies 2-space indentation; Minify collapses it to a single line. If the JSON is invalid, a bottom bar shows the error with exact line and column.
- Hex — editable tab that shows the content in hexadecimal (uppercase pairs, 16 bytes per line). Accepts whitespace, line breaks, and an optional 0x prefix when pasting.
- Base64 — editable tab with the content in standard base64 (RFC 4648). Accepts whitespace when pasting.
- Image — previews the current bytes as an image if interpretable (PNG, JPEG, GIF, etc.). Refreshes live as you edit Hex or Base64. The image zooms: pinch with two fingers, turn the wheel with the pointer over it, or use the buttons at the bottom, which carry the percentage between them and the ⌘−, ⌘+ and ⌘0 shortcuts. The range runs from 100 %, which is the image fitted to the frame, to 800 %; a double click —double tap on iPad— toggles between fitted and 200 % anchored where you touched, and dragging pans it without coming away from the edge.

Each editable tab provides Format (re-indents valid bytes), Paste (reads from the clipboard), and Reset (returns to the original value). If the typed content cannot be decoded, a red badge indicates so and the OK button is disabled.

Save or discard
- Save — prepares the UPDATE statement and opens it in the Change Preview before executing; it is never run directly.
- Cancel — closes without modifying the row. The original cell remains unchanged.

Constraints
- If the table has no primary key or the row cannot be uniquely identified, the Save button is disabled. Calíope then suggests running the UPDATE statement manually.
- For NULL values, use the Value › Set NULL menu inside the editor; do not type the literal word in the text field.
- The editor delivers the bytes to the UPDATE pipeline as a UTF-8 string. Bytes that do not form valid UTF-8 (for example raw 0xDEADBEEF) are replaced by the replacement character when saved; for those cases prefer building the UPDATE manually with UNHEX('…') or 0x… literals.

Keywords: advanced cell editor, cell, long text, json, blob, binary, varbinary, hex, format json, complex edit, ⌘E, update, preview

Comparing results of two queries

Run the same query against two different databases or servers and see the differences row by row.

Where it is: SQL Editor › Run on two databases…

The Result Comparison view lets you run a single query against two different sessions — for example, production vs. staging, or two replicas — and see the differences row by row and cell by cell.

How to launch a comparison
- Open the SQL Editor in one session, write the query, and expand the Run ▸ menu in the view's toolbar.
- Choose Run on two databases… and select the second database or server to compare against. Both executions run in parallel.
- When they finish, the results grid is replaced with the compared view.

Summary bar (top)
- Two "badges" with each database's color: blue = primary, orange = secondary. Each shows the session name, row count, and elapsed time (ms).
- Diff indicator: green ✓ Identical when everything matches, or orange ⚠︎ indicating how many values differ (N diffs) and how many rows only exist on one side (M extra rows).
- Diffs only toggle — filters the table to show only rows with a difference.

Comparison grid
- Each row starts with an indicator:
- = (gray) — the row is identical on both sides.
- P (blue) — primary-side row.
- S (orange) — secondary-side row.
- Rows with different values appear paired (P above, S below) with divergent cells highlighted in red (primary) or green (secondary).
- Rows that exist on only one side appear with a more intense tinted background.

Other states
- Affected rows — if the query is an INSERT/UPDATE/DELETE, the view shows large counters side by side with the label Identical affected rows or the numeric difference.
- Error on one or both — if an execution failed, the error block appears with a monospaced (selectable) message.
- Column mismatch — if the two queries returned different column sets, they are listed side by side with + for extras and for common columns.

Context menu on a cell
- Copy — copies the exact value to the system pasteboard.

Notes
- Row order comes straight from each engine; for stable comparisons always use explicit ORDER BY.
- NULL values render in dim red with the literal label NULL.

Keywords: compare, comparison, diff, differences, two databases, two servers, primary, secondary, diffs only, identical rows, affected rows, column mismatch, dual, side by side

View and edit spatial data on a map

How GEOMETRY columns are read, how they are drawn, and how to edit them without writing SQL by hand.

Where it is: SQL Editor › Map

A GEOMETRY column — POINT, LINESTRING, POLYGON and their multiple variants — no longer shows up as a handful of bytes: Caliope displays it as WKT text in the grid, exactly as ST_AsText would write it, and draws it on a map.

Opening the map

With a result that has at least one spatial column, the Map button in the results bar opens a panel below the grid. Drag the separator to share the height with the rest of the editor, just like the chart or the terminal.

If the result has several spatial columns, a picker on the left chooses which one is drawn. Points appear as pins, lines and polygons as strokes; a polygon with holes is drawn with its holes.

Whatever is not drawn is stated

The foot of the panel shows the counts that explain the difference between the rows in the result and what is on the map: how many rows have no geometry, how many fell outside the drawing ceiling — ten thousand geometries — and how many could not be read. A row that isn't shown never disappears silently.

Editing

The mode picker has three positions. In Explore you only look. In Move, pins can be dragged: when you drop one, Caliope composes the UPDATE and shows it before running it — nothing is written until you press Apply, and if you cancel, the pin returns to its place. In Add, a tap on the map proposes the INSERT of a new geometry.

Selecting a line or a polygon in Move mode reveals its vertices: the round ones are dragged to move them, and the ones marked +, halfway along each segment, create a new vertex when dragged. A polygon's rings stay closed on their own.

The Clear button sets the selected row's geometry to NULL without deleting the row.

When editing is not available

If you see a padlock instead of the mode picker, the map is read-only. There are two cases, and the reason appears on hover: the query does not make it clear which table would be written to — a JOIN, a view, a subquery — or the result has no reliable primary key. Without one, an UPDATE could reach several rows, so Caliope would rather not offer it. Adding the primary key to the SELECT is usually enough.

The order of the coordinates

In POINT(a b), which of the two numbers is the latitude depends on the server and the reference system, and it is no small detail: get it backwards and a point in Madrid ends up in the Indian Ocean. MySQL 8 with SRID 4326 writes latitude first, because that is what EPSG:4326 declares; MariaDB and SRID 0 write longitude first. Caliope resolves this on its own — it displays and writes in the same order as the server — which is why the cell text always matches what ST_AsText returns on that same server.

Keywords: spatial, gis, map, geometry, point, polygon, linestring, coordinates, latitude, longitude, srid, wkt, geolocation, mapkit

Column Profiler

Detailed statistics for a result column: min, max, avg, NULLs, distinct values, and top values.

Where it is: Results Grid › right-click › Profile Column…

The Column Profiler analyzes the values of any column in a SQL query result.

How to activate it:
- macOS: right-click a column header in the results grid and select Profile Column…
- iPad: tap the Profile Col. button in the results bar to open the panel with the column selector.

Information displayed:
- Total rows, NULL count and percentage
- Distinct values and their percentage
- Minimum, maximum, and average (if the column is numeric)
- Top 8 most frequent values with a bar chart

Calculations are performed on already-loaded rows, without running additional queries to the server.

Keywords: column profiler, statistics, min, max, avg, NULL, distinct, histogram, frequency

Execution Profile (SHOW PROFILE)

Breaks down the internal phases of a query with their execution times.

Where it is: SQL Editor › Profile

The Query Profiler uses SET profiling = 1 and SHOW PROFILE FOR QUERY n (MySQL/MariaDB syntax) to obtain the breakdown of MySQL's internal phases when executing a query.

How to activate it: click the Profile button in the SQL Editor results bar. Calíope re-executes the current query and displays the phases (parsing, optimizing, executing, sending data, etc.) with their duration in milliseconds.

The horizontal bar chart visually highlights the most expensive phases. The % column shows what fraction of the total time each phase consumes. If a phase exceeds 50% it is marked in red.

> Note: SHOW PROFILE requires the have_profiling = YES variable on the server. It may not be available in modern MySQL 8.0+ versions where it was deprecated; in that case, use Visual EXPLAIN instead.

Keywords: SHOW PROFILE, profiling, phases, execution, parsing, optimizing, sending data, performance

Index Advisor

Detects full scans in the execution plan and suggests CREATE INDEX statements.

Where it is: SQL Editor › Indexes

The Index Advisor asks for the execution plan of the current query and looks in it for full table scans.

How to activate it: click Indexes in the results bar. Calíope displays:

1. The translated plan, node by node, with the same vocabulary and the same colors as Visual EXPLAIN: full scans come out in red.
2. The suggestions, with the reason and buttons to copy the SQL or insert it into the editor. If the query filters by a column no index covers, the suggestion is a CREATE INDEX on that column; if it filters by none, no index avoids the scan and the suggestion says so as a comment, instead of proposing an index that would not help.

If there are no full scans, a green badge appears. The advisor covers the most common case; for the whole tree, with its rows and its detail, use Visual EXPLAIN.

Keywords: EXPLAIN, index, full scan, Full Table Scan, CREATE INDEX, optimization, performance, advisor

Result Chart

Visualize query results as a bar, line, or pie chart.

Where it is: SQL Editor › Chart

The Result Chart converts the rows of a SELECT query into an interactive visualization using Swift Charts.

How to activate it: run a query that returns data and click Chart in the results bar. The chart panel appears below the grid.

Controls:
- Type: Bar, Line, or Pie
- X Axis: column used as the label (recommended: text or date)
- Y Axis: numeric column to be plotted
- Max: maximum number of rows to chart (5–500)

The chart automatically detects numeric columns and selects the most sensible values. Works on macOS, iPad and iPhone.

Keywords: chart, bar, line, pie, visualize, Swift Charts, result, graph

Query Benchmark

Measure the execution time of a SQL query across multiple iterations with detailed statistics.

Where it is: SQL Editor › Benchmark

The Benchmark runs the active editor query N times and calculates performance statistics, allowing you to detect timing variations and evaluate the impact of index or structural changes.

How to activate it:
Press the Benchmark button (stopwatch icon) in the SQL Editor toolbar. A sheet opens with the active query's SQL pre-loaded.

Controls:
- Iterations — use the stepper to choose how many times the query runs (1–1000, increments of 10). The default is 10 iterations.
- Start benchmark — begins execution. The button is disabled if the editor is empty.
- Stop — cancels the current run and retains the results accumulated up to that point.

Displayed metrics:
- Total — sum of all execution times in ms.
- Average — arithmetic mean of execution times.
- Minimum — the fastest execution.
- Maximum — the slowest execution.
- Std. Dev. — standard deviation: high values indicate inconsistency in timings (possible server contention or variable load).

Bar chart: each bar represents one iteration. Bars are colored green (fast), yellow (intermediate), or red (slow, more than 66% of the maximum) to visually identify outliers.

Use cases:
- Compare query time before and after creating an index.
- Verify whether the server responds consistently under load.
- Measure the impact of changes to the WHERE clause or JOINs.

Available on macOS, iPad and iPhone.

Keywords: benchmark, performance, iterations, time, statistics, average, minimum, maximum, standard deviation, stopwatch, measure