This page describes Calíope 1.8, the version I am building right now. 1.7 is on the App Store for the Mac, iPad, iPhone, Apple Watch, Apple TV and Apple Vision Pro. 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.
Navigate tables, views, indexes, columns, routines, triggers, and events.
Where it is: Workspace › Tools › Catalogs
Open Catalogs from the workspace navigation bar. Select a database in the top selector. The sub-tabs display the different categories of objects.
ClickHouse
With ClickHouse there are no Triggers or Events tabs, and a note under the tabs says what takes their place. Indexes is called Keys: for each table, the sorting key, the partition key, the primary key if it differs, the sampling key, the skip indexes with their type and granularity, and the projections, with no cardinality and no New index. Between Views and Keys sits Materialized views: the list says what each one writes to —Internal, if the server created the target— and when it refreshes, and below it goes the sheet of the selected one: which table it reads from, which table it writes to and the name to query it by, how much space the target takes and how many rows it has, when the last row was written and, if it refreshes on its own, its schedule, its status and the last and next refresh, with the time zone written out. Routines lists the user's functions, which are lambdas and are created and edited from here.
Oracle
With Oracle the selector lists schemas: those with some object your account can see, plus your own even when empty, Oracle’s included (SYS, MDSYS…). Tables shows the user’s tables —without the internal ones of a spatial index or a materialized view—, with the rows from the last statistics (NUM_ROWS) and the types as Oracle writes them (NUMBER(10,0), VARCHAR2(100 CHAR)). Materialized views have their own tab, Materialized views: the table that stores their rows, which tables they read, when and how they refresh, the last refresh and whether they are up to date, with Refresh now. Routines lists procedures, functions and packages —with their specification and body in the DDL panel— and puts INVALID after the type of one that does not compile; Triggers puts DISABLED after one that is disabled. In Indexes, a function-based index shows its expression, and a domain or anomalous one, its type (DOMAIN · MDSYS.SPATIAL_INDEX_V2, NORMAL · INVISIBLE, UNUSABLE). There is one more tab, Sequences, with minimum, maximum, step, cycle, cache and Next on disk: the next number the server will write, not the last one it handed out, which with a cache can be up to a block behind. Events lists the schema’s DBMS_SCHEDULER jobs.
SQL Server
With SQL Server, Indexed views sits between Views and Indexes: views with a unique clustered index that stores their rows. The card of the selected one says which index, how much it takes, how many rows it has and which tables it reads from, and its DDL carries the indexes after it; they no longer appear under Views, although the editor tree, backups and the comparator still treat them as views. Sequences lists the schema’s ones with minimum, maximum, step, cycle, cache and Last handed out: the last number NEXT VALUE FOR gave.
Display the CREATE TABLE, CREATE VIEW, or CREATE PROCEDURE and edit it interactively.
Where it is: Catalogs › context menu › View DDL
Open the context menu —right-click on macOS, long press on iPad— of any object in the catalogs list and select View DDL. The bottom panel shows the full DDL with syntax highlighting and text selection on every platform.
Editing the DDL:
Press Open in ItemEditor (button at the top of the DDL panel) to open the editor in a modal sheet with the DDL pre-loaded. It is the same editor on every platform, with syntax highlighting.
Modify the DDL as needed and press Apply to send it to the server. The Reset button discards your changes and reverts to the original DDL. If the ALTER or CREATE fails, a red message appears in the bottom bar with the server's error.
Available on macOS, iPad, iPhone and Apple Vision Pro.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Oracle
With Oracle the panel shows what the server writes with DBMS_METADATA.GET_DDL: quoted and qualified names, EDITIONABLE where it applies, the whole identity and, for a table, its indexes, its comments and its foreign keys at the end, as ALTER TABLE. If your account cannot read the DDL of an object in another schema —it lacks SELECT_CATALOG_ROLE—, a comment says so and Open in ItemEditor is not offered. Sequences also have View DDL.
Create a table directly from the Catalogs toolbar.
Where it is: Catalogs › New table
In the Catalogs toolbar, use the New table button to open the Table Builder in a new tab. You can also open the context menu on an existing table — right-click on macOS, press and hold on iPad — and choose Design table to edit it.
The builder splits the work across the tabs of its bar: Columns, Indexes, Foreign keys —where the engine has them— and Options. What each one offers with your session's engine is covered in the Table Builder topics.
The SQL Preview section at the bottom shows the DDL that will be executed in real time. Press Create table (or Apply changes in edit mode) to send the DDL to the server.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Access the visual editors for each object type from the toolbar.
Where it is: Catalogs › New view / New index / New routine / New trigger / New event
The Catalogs toolbar includes dedicated buttons to create each object type:
- New view — opens the view editor
- New index — opens the index editor
- New routine — opens the function and stored procedure editor
- New trigger — opens the trigger editor
MySQLMariaDBAurora
- New event — in the Events tab, opens the event scheduler editor
SQL Server
With SQL Server, Events are the Agent jobs whose step runs in this database, listed under its dbo, and New event creates one. In Express, which has no Agent, the tab says why it is empty.
PostgreSQL
Events are the jobs of the pg_cron extension, listed in its schema, cron: New event schedules them with cron.schedule. Without the extension, the Events tab says what is missing.
Each editor generates the corresponding DDL (CREATE VIEW, CREATE INDEX, CREATE PROCEDURE, etc.) in the dialect of the server you are connected to, and executes it on the server upon confirmation. Each one only offers what that server can write: the next topics say what changes from one engine to another.
ClickHouse
With ClickHouse there are New view and New routine, which creates a lambda function: there is no New index —the tab is Keys, and a skip index is added from the Table Builder—, no New trigger and no Events tab.
Oracle
With Oracle you get New view, New index, New routine —a procedure or a function—, New trigger and New event, which is a DBMS_SCHEDULER job. A package is edited, but not created from here.
TiDB
With TiDB there are New view and New index. There is no New routine, no New trigger and no Events tab: TiDB has no stored routines, triggers or event scheduler, and Catalogs says so in a note. Its sequences are listed in the Sequences tab, with their DDL.
Modify existing objects with the visual editor or directly in the SQL editor.
Where it is: Catalogs › context menu › Edit (visual form) / Open in ItemEditor
Open the context menu on a view, routine, trigger, or event in its corresponding Catalogs tab — right-click on macOS, press and hold on iPad. Besides View DDL, it offers two ways to edit:
- Edit (visual form) — opens the graphical editor with pre-filled fields
- Open in ItemEditor — opens the full DDL of the object in the SQL editor for manual modification
Changes made in the visual form generate an ALTER or DROP + CREATE depending on the object type.
MariaDB
With MariaDB, routines, triggers and indexes are replaced in one statement (CREATE OR REPLACE): if it fails, the object you had is still there.
Oracle
With Oracle you can edit procedures, functions, packages, triggers and the DBMS_SCHEDULER jobs listed under Events. A trigger with several events, UPDATE OF columns, its own REFERENCING or COMPOUND, and a routine whose header the form cannot write, open but are not saved from the sheet: Open in ItemEditor takes them to the SQL editor.
ClickHouse
With ClickHouse, user-defined functions are edited with Edit (visual form), which opens the Routine editor with their parameters and their expression, and Open in ItemEditor takes their DDL to the SQL editor.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Where it is: Catalogs › context menu › Populate with dummy data
Open the context menu on a table in the Tables tab of Catalogs — right-click on macOS, press and hold on iPad — and select Populate with dummy data. You can also select the table and press Populate table in the Catalogs toolbar. In read-only mode it doesn't appear.
You choose how many rows you want, from 1 to 5000, and the sheet shows each column with its type and a sample value before it starts. Calíope reads the columns and their types from the server and skips auto-increment and computed columns, which the engine fills in. Foreign key values are random too, so they may not exist in the parent table.
It inserts in batches of 50 rows, with a progress bar. If the server rejects a batch, the load stops and tells you why. When it finishes, it says how many rows went in according to the server, how many it discarded without an error and whether it warned about values it adjusted.
MySQLMariaDBAuroraTiDB
An ENUM or SET column gets values from its own list. During the load the foreign key check is turned off, so you can end up with rows that point to a parent that doesn't exist: they're useful for testing a JOIN with no match. A row with a repeated key or a CHECK that fails is discarded without an error, so fewer rows than you asked for may go in. A value out of range isn't discarded: it goes in clipped to the type's limit — a TINYINT of 300 ends up as 127 — and leaves a warning.
PostgreSQL
During the load the table's triggers don't fire, including the ones that check foreign keys, so you can end up with rows that point to a parent that doesn't exist. A row that repeats a unique key is discarded without an error. Turning the triggers off requires a superuser: without one, the load goes on with foreign keys checked, the final message says so, and a batch with a value that doesn't exist in the parent table stops with its warning.
SQL ServerOracle
The foreign key check stays on: a batch with a value that doesn't exist in the parent table stops with its warning, and so does one with a repeated key.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Keywords: dummy data, seed, test data, populate, fake data
Prevents accidental modifications to catalog objects.
Where it is: Catalogs › Read only
Catalogs opens in Read-only: the toggle in its toolbar is on and the create and delete buttons are disabled. Turn it off to create or drop objects, and turn it back on when you explore a production database. If the connection carries a read-only environment tag, the switch isn’t there, and neither are the create and delete buttons: that session can’t write, so there is nothing to unlock.
Keywords: read only, read-only, protect, production
Create or modify a view; the options it offers depend on the engine.
Where it is: Catalogs › New view / Edit view
The View Editor opens when you press New view, or from the context menu of an existing view — right-click on macOS, press and hold on iPad — with Edit (visual form). It automatically generates the CREATE VIEW DDL.
Available fields:
- Name — name of the view in the selected database.
- The replace toggle — when enabled, the generated DDL replaces the view if it already exists, without dropping it first. The toggle is named after the clause it writes:
MySQLMariaDBAuroraPostgreSQLOracleTiDB
OR REPLACE — CREATE OR REPLACE VIEW.
SQL Server
OR ALTER — CREATE OR ALTER VIEW.
MySQLMariaDBAurora
- Algorithm — controls how the server processes the view:
- UNDEFINED (default) — the server chooses the optimal algorithm.
- MERGE — merges the view query with the outer query. More efficient.
- TEMPTABLE — materializes the view into a temporary table before applying external filters.
- SQL Security — defines the privileges under which the view executes:
- DEFINER (default) — executes with the privileges of the user who created it.
- INVOKER — executes with the privileges of the user querying it.
TiDB
TiDB accepts Algorithm and SQL Security and keeps them in its SHOW CREATE VIEW. No TiDB view can be written to (IS_UPDATABLE is NO): rows are changed in its tables.
- CHECK OPTION — validates that rows modified through the view remain visible in it:
- LOCAL — only checks the condition of this view.
- CASCADED — also checks conditions of underlying views.
- SQL SELECT — the text editor with the SELECT query that defines the view's content.
Press Apply to execute the DDL on the server.
SQL ServerPostgreSQLOracle
There is no Algorithm or SQL Security: the sheet doesn't show them.
SQL ServerOracle
WITH CHECK OPTION has a single form, the one CASCADED describes: choosing LOCAL writes that one, and the sheet says so.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Create or modify stored procedures and functions with a visual interface.
Where it is: Catalogs › New routine / Edit routine
The Routine Editor opens when you press New routine or edit an existing routine from the Routines tab of Catalogs. It generates the DDL that creates the procedure or function, or replaces the one with that name:
TiDB
With TiDB this editor does not open: TiDB has no stored routines (it rejects CREATE PROCEDURE and CREATE FUNCTION), and Catalogs has no Routines tab.
MySQLAurora
Two statements, run one after the other: DROP PROCEDURE IF EXISTS and CREATE PROCEDURE (or DROP FUNCTION IF EXISTS and CREATE FUNCTION). MySQL has no CREATE OR REPLACE for routines, so the existing routine is dropped first: if the creation fails, it is no longer there.
MariaDB
One statement: CREATE OR REPLACE PROCEDURE or CREATE OR REPLACE FUNCTION. If it fails, the routine you had is still there.
PostgreSQL
CREATE OR REPLACE PROCEDURE or CREATE OR REPLACE FUNCTION.
SQL Server
CREATE OR ALTER PROCEDURE or CREATE OR ALTER FUNCTION.
Available fields:
- Name — name of the procedure or function.
- Type — select between PROCEDURE (procedure) or FUNCTION (function).
- Parameters — add parameters with the + button. Each parameter has:
- Mode: IN (input), OUT (output), INOUT (input and output). Only available for procedures.
- Name of the parameter.
- Data type (e.g. INT, VARCHAR(100), DATETIME).
- Return type (functions only) — the data type returned by the function (e.g. INT, VARCHAR(255)).
- Body — text editor with the code of the routine. It starts as an empty BEGIN … END block to write inside.
The Options section only shows what the server can write:
MySQLMariaDBAurora
- Deterministic — writes DETERMINISTIC if the routine always returns the same result for the same input parameters. Important for replication.
- Data access — declares the routine's behavior regarding the database:
- CONTAINS SQL — may contain SQL but does not read or write data.
- NO SQL — contains no SQL statements.
- READS SQL DATA — reads data but does not modify it.
- MODIFIES SQL DATA — may insert, update, or delete data.
PostgreSQL
Only Deterministic, and only for functions: it writes IMMUTABLE —the function always returns the same result for the same arguments and doesn't read the database—. A procedure has no such option, and there is no Data access: PostgreSQL has no such clause. Language picks the body’s language among those the server has: plpgsql by default, sql and any others installed; editing a routine keeps its own. Two functions with the same name and different arguments —an overload— appear in the list each with its signature, precio(integer) and precio(text), and are edited and dropped separately.
SQL Server
There is no Options section: SQL Server works out by itself whether a function is deterministic, and has no data access clause. A parameter that is not IN is written @name type OUTPUT, and the @ is added if you leave it out.
Press Apply to execute the DDL on the server.
Oracle
With Oracle the editor writes CREATE OR REPLACE PROCEDURE or FUNCTION with the parameters as they were written —with their DEFAULT and %TYPE—, RETURN and DETERMINISTIC, and keeps what the header carries and the form does not show (AUTHID, RESULT_CACHE…). The body is what follows AS: the declarations and the block. A package is edited whole: its specification and its body, separated by a line with /. If the server stores it with compilation errors, the sheet shows each ALL_ERRORS line and does not report it as created.
ClickHouse
With ClickHouse routines are lambda functions: the editor only offers FUNCTION, parameters have a name and no type, there is no return type and no Options, and the body is an expression that names the parameters (k * x + b). It writes CREATE OR REPLACE FUNCTION name AS (x, k, b) -> k * x + b. The function belongs to the server, not to a database: its name carries no database in front. When you edit it, the body is the expression as the server stores it, with its parentheses.
Keywords: routine, procedure, function, PROCEDURE, FUNCTION, parameters, IN, OUT, INOUT, deterministic, CONTAINS SQL, CREATE PROCEDURE, CREATE FUNCTION
Where it is: Catalogs › New trigger / Edit trigger
The Trigger Editor opens when you press New trigger in the Catalogs toolbar, or from the context menu of an existing trigger — right-click on macOS, press and hold on iPad — with Edit (visual form). The schema tree does not open it: its context menu opens none of the Catalogs editors.
TiDB
With TiDB this editor does not open: TiDB has no triggers (it rejects CREATE TRIGGER), and Catalogs has no Triggers tab.
Available fields:
- Name — name of the trigger.
- Timing — when the trigger fires relative to the operation:
MySQLMariaDBAuroraPostgreSQL
- BEFORE — executes before the operation. Allows modifying NEW values before they are written.
- AFTER — executes after the operation.
SQL Server
- AFTER — executes after the operation.
- INSTEAD OF — replaces the operation with the trigger's code.
There is no BEFORE.
- Event — the operation that fires the trigger:
- INSERT — when a row is inserted.
- UPDATE — when a row is updated.
- DELETE — when a row is deleted.
- Body — text editor with the trigger code. The starter body says, in comments, where the new and previous rows are.
Press Apply to execute the DDL on the server.
MySQLMariaDBAuroraPostgreSQL
The trigger fires once per row: NEW.column is the new value (in INSERT and UPDATE) and OLD.column the previous one (in UPDATE and DELETE).
PostgreSQL
A trigger's code lives in a function: Calíope creates the function <name>_fn with the body and the trigger that calls it, FOR EACH ROW. The body ends with RETURN: in a BEFORE trigger the row it returns is the one written, and NULL skips the row. The starter body returns COALESCE(NEW, OLD), which is right for the three events. Editing a trigger without renaming it replaces it in one statement, CREATE OR REPLACE TRIGGER, from PostgreSQL 14; before that, it is dropped and created again.
SQL Server
The trigger fires once per statement, not once per row, and the new and previous rows are in the inserted and deleted tables, not in NEW and OLD: the starter body says so. Editing a trigger without renaming it replaces it in one statement, CREATE OR ALTER TRIGGER, from SQL Server 2016 SP1: there is no moment without the trigger, and if the new body does not compile the previous one stays; before that, it is dropped and created again.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Oracle
With Oracle the timing is BEFORE, AFTER or INSTEAD OF —the last one, on a view—, and there are two more switches: For each row (FOR EACH ROW) and Enabled (ENABLE or DISABLE). Saving is CREATE OR REPLACE TRIGGER, and any WHEN condition it had is kept. One with several events, UPDATE OF columns, its own REFERENCING or COMPOUND opens, but is not saved from here. If the server stores it with compilation errors, the sheet shows each ALL_ERRORS line.
The Event Editor opens when you press New event in the Catalogs toolbar or edit an existing event. Requires the MySQL Event Scheduler to be enabled (SET GLOBAL event_scheduler = ON).
Available fields:
- Name — name of the event.
- Status — controls whether the event is active:
- ENABLE — the event executes according to its schedule.
- DISABLE — the event is paused.
- SLAVESIDE_DISABLED — disabled on a replication replica.
- Schedule type:
- One-time (AT) — executes at a specific date and time. Use the date/time picker to set the moment.
- Recurring (EVERY) — repeats every N time units. Configure the number and unit (SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR).
- Start (recurring) — when the recurring event begins executing.
- Dates and times are server time, with no time zone: the picker shows what the server has stored, not your device's clock.
- End date (recurring, optional) — enable the toggle to define when it stops executing.
- Body — SQL code executed by the event. Can be a BEGIN … END block with multiple statements.
Press Apply to execute the DDL on the server.
PostgreSQL
With PostgreSQL the event is a pg_cron job: the editor writes cron.schedule(name, expression, body), which replaces a job that already has that name, and DISABLE leaves it inactive with cron.alter_job. There are only recurring ones: every N seconds (up to 59), minutes or hours that divide the hour and the day, and every day, week, month or year, at the start time in UTC. A one-time run or an end date do not exist in pg_cron, and the SQL preview says so. A job with any other cron expression shows in its DDL but does not open the editor.
SQL Server
With SQL Server the event is an Agent job with one T-SQL step that runs in this database: the editor writes sp_add_job, sp_add_jobstep, sp_add_jobschedule and sp_add_jobserver, and when editing, sp_update_job, sp_update_jobstep and sp_update_schedule, which keep its history. Jobs belong to the server, not to a schema: they are listed in the dbo of the database their step runs in, and in any other schema the tab says where they are. A job with several steps, or with a schedule the editor does not write, shows in its DDL but does not open the editor. Express and Azure SQL Database have no Agent, and there the tab doesn't appear.
Oracle
With Oracle the event is a DBMS_SCHEDULER job of the schema, a PL/SQL block: the editor writes DBMS_SCHEDULER.CREATE_JOB with job_type => 'PLSQL_BLOCK', and when editing, SET_ATTRIBUTE, ENABLE and DISABLE, which keep its history; a new name drops the job and creates it again. The schedule is FREQ=…;INTERVAL=n, with times in UTC. A job with another calendar, with a program or that is not a block shows in its DDL, but does not open the editor. Creating requires the CREATE JOB privilege.
Create an index on a table with configurable type, method, and columns.
Where it is: Catalogs › New index / Create index
The Index Editor opens from the Indexes tab of Catalogs: with a table selected, the New index button in the toolbar; on an index that already exists, the context menu — right-click on macOS, press and hold on iPad — with Edit (visual form). The schema tree does not open it.
Available fields:
- Name — name of the index on the table.
- Type:
- INDEX — standard index, allows duplicates.
- UNIQUE — unique index, rejects duplicate values in the indexed column or column combination.
MySQLMariaDBAurora
- FULLTEXT — full-text search. Only for CHAR, VARCHAR, or TEXT columns and the MyISAM/InnoDB engine (MySQL 5.6+).
- SPATIAL — geospatial data. Only for spatial-type columns, with MyISAM or InnoDB (MySQL 5.7+, MariaDB 10.2+).
SQL Server
- SPATIAL — geospatial data, on a geometry or geography column of a table with a primary key. For geometry you write the Box that bounds the data (xmin, ymin, xmax, ymax); for geography you leave it empty.
MySQLMariaDBAuroraPostgreSQL
- Method (for INDEX and UNIQUE):
- BTREE — B-tree, the most common method. Supports range comparisons, LIKE 'abc%', ORDER BY.
- HASH — hash table, only supports exact equality comparisons.
MySQLMariaDBAurora
HASH is only honoured by the MEMORY engine.
PostgreSQL
A UNIQUE index can't be HASH, so with UNIQUE the method is BTREE. Besides BTREE and HASH it offers GIN —for jsonb, arrays and full text—, GIST and SPGIST —geometry and ranges— and BRIN, for very large tables ordered by insertion; editing an index keeps its own. The Build without blocking writes (CONCURRENTLY) checkbox creates the index without closing the table to writes, at the cost of taking longer.
SQL ServerOracle
There is no Method: CREATE INDEX has no USING clause.
- Columns — add the columns that make up the index with the name field and, optionally, the prefix length (number of characters to index; useful for long TEXT or VARCHAR columns).
SQL ServerPostgreSQLOracle
There is no index prefix: the whole column is indexed, and the generated DDL says so in a comment.
The primary key is managed from the Columns tab of the Table Builder, not from this editor.
Press Apply to execute CREATE INDEX on the server.
ClickHouse
With ClickHouse this editor doesn't open: the tab is Keys and it has no New index. A skip index is added or removed in the Table Builder, on its Indexes tab.
Apple Vision Pro: the context menu opens by looking at the row and pinching and holding.
Oracle
With Oracle the type is INDEX, UNIQUE, FULLTEXT —an Oracle Text index, INDEXTYPE IS CTXSYS.CONTEXT— or SPATIAL —MDSYS.SPATIAL_INDEX_V2, which first registers its USER_SDO_GEOM_METADATA row if missing, with the SRID of the existing geometries, or 4326 on an empty table—; both cover one column, and they only appear if the server has Oracle Text and Spatial. The index is created in its table’s schema. Dropping an index that backs a UNIQUE constraint drops the constraint, and the index with it.
TiDB
With TiDB the types are INDEX and UNIQUE, and the method is BTREE: TiDB accepts FULLTEXT with a warning without creating the index, and has no spatial types to index.
Keywords: index, CREATE INDEX, UNIQUE, FULLTEXT, SPATIAL, BTREE, HASH, columns, prefix, ALTER TABLE, index editor
The search field filters by name the list of the open tab and empties when you switch tabs; refreshing reads the database again, and the list reloads by itself when another Calíope tool changes it.
Where it is: Workspace › Tools › Catalogs
The search field in the Catalogs bar filters by name the list of the tab that is open —tables, views, indexes, routines and the rest— and empties itself when you switch tabs.
The Refresh button reads the database again. You will rarely need it: when another Calíope tool creates or drops an object in that database, the list reloads by itself. Changes made from outside Calíope appear after refreshing.
The context menu of a table, an index, a routine or an event offers to delete it; the confirmation shows the DROP the engine will run.
Where it is: Workspace › Tools › Catalogs
The context menu of a table, an index, a routine or an event offers to delete it. Before doing anything, Calíope shows the DROP statement the engine will run and asks you to confirm; if the connection carries an environment tag that asks for confirmation, the dialog names it.
Views, triggers and sequences are not deleted from Catalogs: drop them from the SQL Editor.
With the padlock on, the option appears disabled; in a session that can only read, it is not drawn at all.