Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d94a3f0
docs: PluginKit 40 for the shared SQLite foreign key query
datlechin Oct 20, 2026
24a8a1a
docs: show an open transaction on the Mac, and the iOS transaction fo…
datlechin Oct 20, 2026
5b69e91
docs(ios): socket rows in imports, widget skips Mac-only connections,…
datlechin Oct 20, 2026
d1d9725
docs(databases): read Redis commands by line and redis-cli quoting on…
datlechin Oct 20, 2026
7d3790d
Merge branch 'docs/followups-into-3688' into docs/ios-run-follow-ups
datlechin Oct 20, 2026
64bb106
Merge branch 'docs/followups-ios-connections' into docs/ios-run-follo…
datlechin Oct 20, 2026
176a8b8
Merge branch 'docs/followups-mac-sqlite-fk-grouping' into docs/ios-ru…
datlechin Oct 20, 2026
dadbf89
Merge branch 'docs/followups-redis-command-parsing' into docs/ios-run…
datlechin Oct 20, 2026
2d4da33
docs: ClickHouse on iPhone and iPad
datlechin Oct 20, 2026
1ca251c
docs(ios): query suggestions for functions, schemas and enums, the Qu…
datlechin Oct 20, 2026
2972d6e
docs(ssh): SSH profiles on iPhone and iPad, socket forwards, and the …
datlechin Oct 20, 2026
bca20f7
Merge remote-tracking branch 'origin/main' into docs/followups-ios-ss…
datlechin Oct 20, 2026
b5c11e0
Merge remote-tracking branch 'origin/docs/ios-run-follow-ups' into do…
datlechin Oct 20, 2026
032539f
Merge remote-tracking branch 'origin/main' into docs/followups-into-3…
datlechin Oct 20, 2026
f0682bb
Merge remote-tracking branch 'origin/docs/ios-run-follow-ups' into do…
datlechin Oct 20, 2026
b0146b1
docs(ios): saved queries add to the editor as History entries do
datlechin Oct 20, 2026
f128a0e
Merge remote-tracking branch 'origin/main' into docs/followups-into-3…
datlechin Oct 20, 2026
61ecb5c
docs(connections): the Preferred SSL mode on iPhone and iPad, Require…
datlechin Oct 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion connections/aws-iam.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ IAM also requires encryption in transit, so an [SSL mode](/connections/ssl) of *

`web_identity_token_file` is not supported and says so rather than reporting the profile incomplete.

A connect that fails on an expired IAM Identity Center session offers the browser sign-in; `aws sso login --profile <name>` does the same from the shell.
A token from IAM Identity Center renews itself with its refresh token in its last 15 minutes, as the AWS CLI does, and the renewed token goes back into `~/.aws/sso/cache`. A connect that fails because the session itself ended offers the browser sign-in; `aws sso login --profile <name>` does the same from the shell.

## Tunnels and port forwards

Expand Down
2 changes: 1 addition & 1 deletion connections/connection-form.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ A connect you did not start never runs the script. A restored window at launch,

## Startup commands

Statements split on semicolons and newlines and run in order on the connection that just opened, after every connect including an automatic reconnect. They all run on one connection, so write one dialect.
Statements split on semicolons and newlines outside quotes and comments, and run in order on the connection that just opened, after every connect including an automatic reconnect. They all run on one connection, so write one dialect.

<CodeGroup>
```sql MySQL
Expand Down
2 changes: 2 additions & 0 deletions connections/ssh-profiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ Deleting a profile hands its configuration and its secrets to each connection th
## iCloud Sync

Profiles sync across Macs with iCloud Sync on and the **SSH Profiles** toggle set in **Settings > Sync**. Passwords, key passphrases, and TOTP secrets stay in the local Keychain unless the **Passwords** toggle, nested under **Connections**, is on too, and that covers newly saved credentials only: re-save an existing password to include it.

On [iPhone and iPad](/ios#ssh-profiles), a connection that uses a profile keeps the profile's server and jump hosts read only and signs in with the profile's password once it reaches iCloud Keychain. Turning **SSH Tunnel** off there unlinks the profile from that connection on every device.
8 changes: 7 additions & 1 deletion connections/ssh-tunneling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ A first connection shows the server's key type and SHA-256 fingerprint, in `ssh-

If a trusted server's key later changes, an **SSH Host Key Changed** alert lists the previous and current fingerprints. **Connect Anyway** does not answer the Return key. Escape picks **Disconnect**, which is what to take unless you know the server was reinstalled. With jump hosts, every hop's key is verified the same way.

The tunnel offers the post-quantum key exchange `mlkem768x25519-sha256` first, so a server that allows only post-quantum key exchange connects too. A server that allows only `sntrup761x25519-sha512` does not.

## Using ~/.ssh/config

Pick an alias from the **Config Host** picker and `HostName`, `User`, `Port`, `IdentityFile`, `IdentitiesOnly`, `IdentityAgent`, and `ProxyJump` are resolved from the config at connect time. Anything typed into the form overrides the file, which is re-read whenever it or an `Include`d file changes.

`Match` blocks take the criteria ssh does, `localnetwork` and `tagged` included. A tunnel counts as `sessiontype none` with an empty `command`, and a criterion TablePro does not know keeps its block from applying.

`IdentityFile` picks which agent key is offered, not only which key file is read, and a `.pub` is enough. That is how a 1Password or Secretive key gets pinned to a host. `IdentitiesOnly yes` then drops every agent key the config did not name, which is what keeps a thirty-key agent inside a server's `MaxAuthTries`.

<Frame caption="Picking a host from ~/.ssh/config">
Expand Down Expand Up @@ -101,7 +105,7 @@ For a database behind more than one bastion, expand **Jump Hosts** and add each
| **Auth** | **Private Key** or **SSH Agent**. Password auth is not offered for a hop |
| **Key File** | Private key path, under Private Key auth |

With the list left empty and an SSH host that matches a config entry carrying `ProxyJump`, that directive is followed instead.
With the list left empty and an SSH host that matches a config entry carrying `ProxyJump`, that directive is followed instead. A hop's own `ProxyJump` is followed too, but in a list only the first hop's, as `ssh -J a,b` does. `ProxyJump none` turns it off, a hop written as `ssh://user@host:port` reads the same as `user@host:port`, and a hop with no `User` is named in the error before anything is dialed.

A connection with hops syncs to [iPhone and iPad](/ios#jump-hosts) with every hop, its port and its key path intact. A key path names a file on the Mac, so give each hop a key on the device before the connection opens there. The tunnel's own port and auth method make the same round trip: a port you left empty stays empty, so `~/.ssh/config` still decides it.

Expand Down Expand Up @@ -153,6 +157,8 @@ Nothing is listening where that socket points, and the message names which of th

A jump host has no **Agent Socket** field of its own, so its agent comes from `IdentityAgent` or `SSH_AUTH_SOCK`.

`IdentityAgent SSH_AUTH_SOCK` means that variable, as it does for ssh. `IdentityAgent none` turns the agent off: a jump host from `~/.ssh/config` then signs in with its `IdentityFile` keys, and a tunnel set to **SSH Agent** stops with an error naming that line.

### "The SSH agent from … holds no keys."

The agent answered and offered nothing. 1Password serves keys only while it is running and unlocked, and Secretive only while its agent is loaded; unlock it and add the key there. `ssh-add` loads keys into the `SSH_AUTH_SOCK` agent alone, so it is the fix only when that is the socket in the message.
Expand Down
12 changes: 9 additions & 3 deletions connections/ssl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ A new connection starts on the mode that matches the driver's own default, and s
| Driver | Default | What Preferred does |
|---|---|---|
| PostgreSQL, Redshift, CockroachDB | Preferred | libpq's own `sslmode=prefer` fallback to plain TCP. Same as `psql` and DataGrip |
| MySQL, MariaDB | Preferred | Tries TLS, then retries plain on an SSL handshake error. Auth and network errors are not retried |
| MySQL, MariaDB | Preferred | TLS when the server offers it, plain when it does not, and a plain retry after an SSL handshake error. Auth and network errors are not retried |
| SQL Server | Preferred | FreeTDS `encryption=request`: the login over TLS, the rest in plain TCP unless the server forces encryption |
| Teradata | Disabled | Opens a TLS transport, retries on a plain socket if it fails to come up |
| MongoDB, Redis, Cassandra, ClickHouse, Elasticsearch, Typesense, SurrealDB, Weaviate | Disabled | Nothing. No fallback exists, so Preferred forces TLS exactly like Required |
Expand All @@ -66,6 +66,8 @@ A saved connection set to **Disabled** on one of these ports shows a warning und

Verify CA and Verify Identity do not survive a tunnel. An SSH tunnel, Cloudflare tunnel, Cloud SQL Auth Proxy, or SOCKS proxy has the driver connect to `127.0.0.1`, and no server certificate is issued for that, so the mode drops to Required for the tunneled connection and the certificate paths are cleared. TLS itself still runs the whole way to the database; only the certificate check goes. If you need the check, reach the server without a tunnel.

On iPhone and iPad the check does survive an SSH tunnel: MySQL, MariaDB, PostgreSQL, Redshift, Redis and Oracle check the certificate against the host saved in the connection. An Oracle server saved as an IP address is still checked against `127.0.0.1`, and Verify Identity refuses it.

Forwarding to a unix socket drops TLS altogether, because a socket cannot negotiate it. The SSH tunnel encrypts that path instead.

## Troubleshooting
Expand All @@ -84,6 +86,10 @@ Server response: FATAL: no pg_hba.conf entry for host "…", user "…", databas

The PostgreSQL server requires SSL and the connection is set to Disabled. Switch to **Preferred** or **Required (skip verify)**.

### "SSL is required, but the server does not support it"

The MySQL or MariaDB server offers no TLS and the connection is set to Required or stricter, which never falls back to plain text. Turn on TLS on the server, or switch to **Preferred** to allow plain text.

### "Connections using insecure transport are prohibited"

The MySQL server has `require_secure_transport=ON`. Switch to **Preferred** or **Required (skip verify)**.
Expand All @@ -96,7 +102,7 @@ Driver and server share no TLS version or cipher. Update the server, or on a dev

The server's certificate chains to nothing in the system trust store. Set **Verify CA** and fill **Certificate** with the CA's PEM, or drop to **Required (skip verify)** to skip validation.

### "hostname does not match certificate"
### "hostname does not match certificate" / "Hostname verification failed"

The certificate's CN or SAN does not cover the host you typed. Change **Host** to a name the certificate covers.

Expand All @@ -110,7 +116,7 @@ Enter the key's passphrase in **Key Passphrase**, which appears once **Client Ke

## On iPhone and iPad

Four modes, Preferred excluded. MySQL, MariaDB, PostgreSQL, Redshift, and Redis get **CA Certificate**, **Client Certificate**, and **Client Key** rows alongside them. Oracle gets Disabled, Required, and Verify Identity with no certificate rows, so Verify Identity checks the server against the system trust store; an Oracle connection saved with Verify CA does not connect until its mode changes. SQL Server gets only Disabled and Required.
The Mac's five modes, and Preferred does what the table above says for each driver. MySQL, MariaDB, PostgreSQL, Redshift, and Redis get **CA Certificate**, **Client Certificate**, and **Client Key** rows alongside them. Oracle gets Disabled, Preferred, Required, and Verify Identity with no certificate rows, so Verify Identity checks the server against the system trust store; an Oracle connection saved with Verify CA does not connect until its mode changes. SQL Server gets Disabled, Preferred, and Required.

Each row takes a file or pasted text. **Client Certificate** also accepts a PKCS#12 (`.p12` or `.pfx`) and fills in both the certificate and its key from it. iOS cannot read a `.p12` exported without a password, and rejects a private key carrying its own passphrase: strip the passphrase or export a `.p12`.

Expand Down
6 changes: 6 additions & 0 deletions databases/clickhouse.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ The default is **Disabled**, which sends plain HTTP. Any other mode switches the

The CA file may be PEM or DER. **Verify CA** needs one, since it checks no hostname, and a connection without it is refused. If **Verify CA** or **Verify Identity** cannot read the file, the connection fails rather than falling back to the public root store. An imported URL with `ssl=true` opens as Verify Identity, and `sslmode=none` as Required. See [SSL/TLS](/connections/ssl).

## On iPhone and iPad

The ClickHouse driver is compiled into TablePro Mobile and talks to the same HTTP interface. Browsing, queries, and row editing work, with edits matched on every value of the row; creating or altering tables stays on the Mac. Unlike the Mac grid, a save or delete there waits for its mutation to finish, and one is refused when another row holds the same values. See [iPhone and iPad](/ios).

Behind an SSH tunnel, **Verify Identity** checks the certificate against the server's own host name, not the local end of the tunnel.

## Limitations

- No foreign keys and no multi-statement transactions.
Expand Down
2 changes: 1 addition & 1 deletion databases/redis.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Toggle the filter bar to search keys by pattern. Patterns are Redis glob (`*` an

## Redis CLI

Each statement is one command; separate several with `;`. Commands the driver does not recognize go through too, and only the result formatting is type-aware. A recognized command with arguments its result view does not model, such as `FLUSHDB ASYNC` or `CONFIG SET a 1 b 2`, is also sent exactly as typed, so the server answers it as `redis-cli` would. Arguments are quoted the way `redis-cli` quotes them, so `"` and `'` both work and `\xHH` writes a raw byte; unbalanced quotes are rejected rather than guessed at. Redis has no comment syntax and none is stripped, so a `--` or `#` line is sent to the server and fails.
A command ends at a `;` or a line break outside quotes, so each line is its own command and a quoted value may run across lines. Commands the driver does not recognize go through too, and only the result formatting is type-aware. A recognized command with arguments its result view does not model, such as `FLUSHDB ASYNC` or `CONFIG SET a 1 b 2`, is also sent exactly as typed, so the server answers it as `redis-cli` would. Arguments are read the way `redis-cli` reads them: `"` and `'` both quote, `\n` and `\xHH` inside double quotes write a byte, only `\'` is an escape inside single quotes, and a backslash outside quotes is part of the argument, so `DEL victim\` deletes `victim\`. Unbalanced quotes are rejected rather than guessed at. Redis has no comment syntax and none is stripped, so a `--` or `#` line is a command of its own and fails at the server.

```redis
SET mykey "hello" EX 60
Expand Down
2 changes: 1 addition & 1 deletion developers/mcp-tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ Formats are `csv`, `json` and `sql`; pass exactly one of `query` or `tables[]`.

`confirm_destructive_operation` runs one `DROP`, `TRUNCATE` or `ALTER … DROP`. Anything that is not destructive is rejected; use `execute_query` for those. The user approves it first, through your elicitation prompt if your client supports elicitation, otherwise through TablePro's own dialog on their Mac.

`transaction_control` takes `action` as `begin`, `commit` or `rollback`. The transaction stays open across calls until it is committed or rolled back, and it runs on the same session as the user's own tabs, so their editor runs and their grid saves land inside it while it is open. Leave nothing open.
`transaction_control` takes `action` as `begin`, `commit` or `rollback`. The transaction stays open across calls until it is committed or rolled back, and it runs on the same session as the user's own tabs, so their editor runs and their grid saves land inside it while it is open. TablePro shows it above the connection's tabs and on its connections strip entry, with **Roll Back** and **Commit**, until it ends. Leave nothing open.

On Redis the three actions are `MULTI`, `EXEC` and `DISCARD`. Every command between `begin` and `commit` answers `QUEUED` and does nothing until `commit` runs them, and `commit` fails naming each command the server then refused. `rollback` drops the block whole.

Expand Down
2 changes: 1 addition & 1 deletion features/autocomplete.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Comments suppress completion, and a brace or bracket inside a string literal doe

## On iPhone and iPad

The iOS query editor completes keywords, tables, views, columns and aliases by the same rules, in the bar above the keyboard: see [Querying](/ios#querying). Functions, operators, schema names, enum values and favorite keywords are Mac only.
The iOS query editor completes keywords, tables, views, columns, aliases, the engine's functions and operators, schema names and enum values by the same rules, in the bar above the keyboard: see [Querying](/ios#querying). Favorite keywords are Mac only.

## My new table does not complete

Expand Down
8 changes: 8 additions & 0 deletions features/sql-editor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ PostgreSQL, Redshift, CockroachDB, MySQL, MariaDB, TiDB, SQLite, DuckDB, SQL Ser

Two things survive a rollback in any of those four cases. MySQL, MariaDB and Oracle commit a `CREATE`, `ALTER` or `DROP` the moment it runs, along with everything before it, and CockroachDB commits the open transaction before it processes any DDL at all.

### The open transaction bar

While a session holds a transaction, a bar above every tab of the connection says **Transaction Open**, names the database, and offers **Roll Back** and **Commit**. It shows whoever opened the transaction, a `BEGIN` you ran, a grid save inside one, or an [MCP client's](/developers/mcp-tools) `transaction_control`, and goes once it ends, by its buttons, by a typed `COMMIT` or `ROLLBACK`, or with the session. On PostgreSQL, Redshift and CockroachDB each database keeps its own connection, so two databases with open transactions show a row each. The [connections strip](/features/workspace-rail) marks the entry with an hourglass, so you see it from another connection.

**Transaction Failed** means a statement inside it failed and it can no longer commit, so only **Roll Back** is offered. **Roll Back** asks first at every [Safe Mode](/features/safe-mode) level. **Commit** asks what a typed `COMMIT` asks: nothing at **Silent**, a confirmation at the Alert levels, a confirmation and Touch ID at the Safe Mode levels. At **Read-Only** it is hidden.

Both act on the connection the bar names. When other work ran there after you clicked, they do nothing and say so: check the transaction and try again.

### Statements a transaction cannot hold

One of these anywhere in the batch leaves the whole of it unwrapped. The engine either refuses the statement inside a block, as PostgreSQL refuses `VACUUM`, or applies it and quietly throws it away, as SQLite does with `PRAGMA foreign_keys`.
Expand Down
2 changes: 1 addition & 1 deletion features/workspace-rail.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Each entry keeps its own tabs. Clicking one shows its tabs and returns you to th

Moving between schemas inside one database, such as PostgreSQL's, keeps the entry and its tabs. Tables of the same name in two schemas are told apart by their schema-qualified tab titles.

On PostgreSQL, Redshift, and CockroachDB every database entry keeps its own server connection, so moving between two entries reconnects nothing and leaves each database's open transaction and temp tables where they were. Closing an entry closes its connection and rolls back a transaction still open there, so it asks first when there is one.
On PostgreSQL, Redshift, and CockroachDB every database entry keeps its own server connection, so moving between two entries reconnects nothing and leaves each database's open transaction and temp tables where they were. Closing an entry closes its connection and rolls back a transaction still open there, so it asks first when there is one. An hourglass on the entry's icon means a transaction is open there; on other engines it marks every entry of the connection, since one connection holds the transaction for all of them.

The strip takes the keyboard too. Click into it, then use the arrow keys to move the highlight. Type the start of a connection, database, or schema name to jump to it, and press `Return` to open the entry.

Expand Down
Loading
Loading