diff --git a/connections/connection-form.mdx b/connections/connection-form.mdx index 825f2d6f..c66825f0 100644 --- a/connections/connection-form.mdx +++ b/connections/connection-form.mdx @@ -76,7 +76,7 @@ Encryption sits below the transport. [SSL/TLS](/connections/ssl) covers the mode | **Post-Disconnect Script** | Shell script run once the session ends, after a pre-connect script ran. See [Connection scripts](#connection-scripts) | | **Safe Mode** | Confirms, authenticates or refuses queries before they run. See [Safe Mode](/features/safe-mode) | | **AI Policy** | Per-connection override for the in-app AI agents. **Never** also refuses external clients. Shown while **Enable AI Features** is on | -| **External Clients** | **Blocked**, **Read Only** (the default), or **Read & Write** for MCP clients such as Raycast, Cursor, and Claude Desktop, and for [AppleScript](/developers/applescript). A token's own scope cannot raise it. See the [integration security model](/developers#security-model) | +| **External Clients** | **Blocked**, **Read Only** (the default), or **Read & Write** for MCP clients such as Raycast, Cursor, and Claude Desktop, and for [AppleScript](/developers/applescript) and [Shortcuts](/integrations/shortcuts). A token's own scope cannot raise it. See the [integration security model](/developers#security-model) | | **AI Rules** | Guidance the AI reads on every chat turn for this connection: table conventions, columns to avoid, join hints. Shown while **Enable AI Features** is on. See [AI Assistant](/features/ai-assistant) | | **Local only** | Keeps this connection off iCloud Sync. Shown while **Sync this Mac with iCloud** is on. See [iCloud Sync](/features/icloud-sync) | diff --git a/developers/index.mdx b/developers/index.mdx index c8ac5b06..7c955976 100644 --- a/developers/index.mdx +++ b/developers/index.mdx @@ -6,7 +6,7 @@ description: Pick the surface for the job, find TablePro by bundle ID, and know import StabilityMatrix from "/snippets/stability-matrix.mdx"; What you need back decides the surface. Putting something on screen needs no setup at all; reading -rows back needs AppleScript or a token. +rows back needs AppleScript, Shortcuts or a token. ## Pick a surface @@ -16,6 +16,7 @@ rows back needs AppleScript or a token. | Open a database nobody saved | [Database URLs](/connections/urls), opened by bundle ID | No | **Open External Database Connection?**, with **Always Allow** for a database on this Mac | | Hand over a connection to keep | [Connection import](/developers/connection-import) | No | A review sheet before the connection is saved | | List connections or run a query from a script | [AppleScript](/developers/applescript) | Yes | Automation permission, once per sending app | +| Run a query or add rows from a shortcut | [Shortcuts](/integrations/shortcuts) | Yes | None; the connection's **External Clients** level and Safe Mode apply | | Give an AI client or a long-running tool schema and rows | [MCP](/developers/mcp-protocol) | Yes | A token or the bundled bridge, then each connection on first use | | Get a token for your own extension | [Pairing](/developers/pairing) | A token | The pairing sheet | | Add a database engine or a file format | [A plugin](/development/plugin-development) | Runs inside the app | Trust in the developer who signed it | @@ -23,7 +24,7 @@ rows back needs AppleScript or a token. A launcher needs two of these: AppleScript or MCP to list connections, and a `tablepro://connect/` link to open one. On iPhone and iPad, an integration has [two connection links](/developers/url-scheme#on-iphone-and-ipad) and the -[Shortcuts actions](/integrations/ios-shortcuts). +[Shortcuts actions](/integrations/shortcuts). ## Find the app diff --git a/docs.json b/docs.json index b1efc4c5..36ed310b 100644 --- a/docs.json +++ b/docs.json @@ -182,7 +182,11 @@ }, { "source": "/external-api/ios-shortcuts", - "destination": "/integrations/ios-shortcuts" + "destination": "/integrations/shortcuts" + }, + { + "source": "/integrations/ios-shortcuts", + "destination": "/integrations/shortcuts" }, { "source": "/external-api/mcp-clients", @@ -342,7 +346,7 @@ "integrations/raycast", "integrations/terminal", "integrations/ddev", - "integrations/ios-shortcuts" + "integrations/shortcuts" ] }, { diff --git a/features/query-history.mdx b/features/query-history.mdx index 4d89f6dc..7a18953a 100644 --- a/features/query-history.mdx +++ b/features/query-history.mdx @@ -48,6 +48,7 @@ Search matches partial words, so `cust` finds `customers`. Several words must al | Imports | Import runs | | AI and MCP | Queries run by an AI assistant or an MCP client | | AppleScript | Queries run by [a script](/developers/applescript) | +| Shortcuts | Queries and inserts run by a [Shortcuts action](/integrations/shortcuts) | **My Queries**, the default, is Editor and Explain. Add **Table Browsing** to see what the app sent while you clicked around a table, **Structure Changes** to review what altered a schema and when. diff --git a/integrations/index.mdx b/integrations/index.mdx index 54e3fd27..8da46224 100644 --- a/integrations/index.mdx +++ b/integrations/index.mdx @@ -21,8 +21,8 @@ The terminal, DDEV and iOS Shortcuts work without it. Open a project's database with `ddev tablepro`. - - Add rows or open a connection from Shortcuts on iPhone and iPad. + + Run a query, add rows or open a connection from Shortcuts on a Mac, iPhone or iPad. diff --git a/integrations/ios-shortcuts.mdx b/integrations/ios-shortcuts.mdx deleted file mode 100644 index 62230ab4..00000000 --- a/integrations/ios-shortcuts.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: iOS Shortcuts -description: Add rows to a table or open a connection from the Shortcuts app on iPhone and iPad ---- - -You point an action at a table, hand it a JSON object, and the row lands in the database with the app -still closed. App Intents put three actions in Shortcuts, the Share Sheet and Siri, and two of -them run entirely in the background. - -This is iOS only. On macOS, use the [URL scheme](/developers/url-scheme) and -[MCP](/developers/mcp-tools). - -| Action | Does | Needs | -| --- | --- | --- | -| **Add Row to Table** | Inserts one row from a JSON object or a CSV row. | iOS app build 17 | -| **Add Rows to Table** | Inserts many rows from a JSON array, CSV text, or a file. | iOS app build 17 | -| **Open Connection** | Launches the app on a saved connection. | Any recent build | - -Your build is under **Settings > About** in the iOS app, and the two insert actions do not appear in -Shortcuts on anything older. The iOS app ships on its own schedule; see -[iPhone and iPad](/ios). - -To browse everything the app offers, open Shortcuts, tap the action list, and go to -**Apps > TablePro**. - -## Build one - - - - In a new shortcut, add **Add Row to Table**. - - - Pick a **Connection**, then a **Table** read live from it. **Database or Schema** is optional and - lists schemas on PostgreSQL and the like, databases elsewhere; empty means the connection's own. - SQLite has neither, so it stays empty there. When the connection cannot open, both pickers - show why, such as an SSH host key to check, instead of an empty list. - - - Feed **Row (JSON or CSV)** from a Shortcuts **Dictionary** action keyed by column name, which - builds the row without typing JSON. **Add Rows to Table** has **Rows (JSON or CSV)** and a - **File** field instead. - - - It returns the number of rows inserted, ready for a later step, and speaks *"Added one row to - bookmarks."* - - - -Inserts work on MySQL, MariaDB, TiDB, OceanBase, PostgreSQL, Redshift, SQL Server, SQLite, DuckDB and -Oracle. Any other type, Redis for example, fails with *"Redis connections do not support adding rows -from Shortcuts."* - -Siri takes "Open [connection] in TablePro", "Connect to [connection] in TablePro", "Add a row in -TablePro" and "Add rows in TablePro", with a connection name in place of the brackets. - -## Data formats - -Keys match columns by name. A column you leave out stays out of the `INSERT` and takes its default, -and an empty or `null` primary key is dropped for the same reason, so auto-increment still fires. - -### JSON - -An object is one row; an array of objects is many, for **Add Rows to Table**. - -```json -{ "title": "TablePro docs", "url": "https://docs.tablepro.app", "tags": "reference" } -``` - -```json -[ - { "title": "First", "url": "https://example.com/1" }, - { "title": "Second", "url": "https://example.com/2" } -] -``` - -`null` inserts a SQL `NULL`, and numbers and booleans are inserted as text. Quote anything that has -to stay exact: a bare JSON number past 64-bit integer range is read as floating point and loses -digits, while `"18446744073709551615"` keeps every one. - -### CSV - -The first row is the header and names the columns. Quoting follows the usual rules. A file can be -UTF-8, UTF-16, Shift JIS, EUC-JP, GB 18030, Big5, EUC-KR or Windows-1252; the encoding is read -from the file. - -```text -title,url -First,https://example.com/1 -Second,https://example.com/2 -``` - -## Limits - -Up to 10,000 rows per run. **Add Rows to Table** runs the batch in one transaction wherever the -engine supports it, so a row that fails rolls back the whole batch instead of leaving half of it in. - -## When it refuses - -Nothing is inserted in any of these cases. - -| Message | Cause | -| --- | --- | -| *"…is read-only, so rows cannot be added."* | The connection's safe mode blocks writes. A connection set to Confirm Writes asks first instead. | -| *"…has no column named …"* | A key in the data matches no column. | -| *"The data has no values to insert into …"* | Nothing in the data maps to a column. | -| *"No data was provided to add."* | Both the text field and the file were empty. | -| *"Line … of the file is not valid … text."* | That line holds bytes the file's encoding cannot read. | -| *"Too many rows. Add up to 10000 rows at a time."* | Over the cap. | -| *"Add Row to Table expects one row. Use Add Rows to Table for multiple rows."* | An array reached the single-row action. | -| *"…check the server's SSH host key first."* or *"…Open this connection in TablePro to check it."* | The SSH server is new, or its host key changed. A Shortcut has no screen to show the question on. | - -The action also fails while the device is locked, because it reads the connection's password from the -Keychain. diff --git a/integrations/shortcuts.mdx b/integrations/shortcuts.mdx new file mode 100644 index 00000000..16c5dbbe --- /dev/null +++ b/integrations/shortcuts.mdx @@ -0,0 +1,160 @@ +--- +title: Shortcuts +description: Open a connection, run a query, or add rows from the Shortcuts app on a Mac, iPhone or iPad +--- + +Every action starts from a saved connection picked from a list. Find them in Shortcuts under +**Apps > TablePro**, in Spotlight, and in Siri. + +| Action | Does | Mac | iPhone and iPad | +| --- | --- | --- | --- | +| **Open Connection** | Opens the connection's window. | Yes | Yes | +| **Run Query** | Runs one statement and passes the result to the next action. | Yes | No | +| **Add Row to Table** | Inserts one row from a JSON object or a CSV row. | Yes | iOS app build 17 | +| **Add Rows to Table** | Inserts many rows from a JSON array, CSV text, or a file. | Yes | iOS app build 17 | + +On a Mac the actions need macOS 14.2 or later. On macOS 13, use [AppleScript](/developers/applescript). +The iOS app's build is under **Settings > About**; it ships on its own schedule, see +[iPhone and iPad](/ios). + +## Run a query on a Mac + + + + In a new shortcut, add **Run Query** and type the statement, such as `SELECT count(*) FROM orders`. + + + **Connection** lists every saved connection whose **External Clients** level is not Blocked. + **Database or Schema** is optional and works as it does for the insert actions. + + + Set **Result** to the shape the next action needs. + + + +| Result | The next action gets | +| --- | --- | +| **Rows**, the default | A list with a dictionary for each row, keyed by column name. | +| **First Value** | The first column of the first row, as text. Nothing when there are no rows or the value is NULL. | +| **CSV** | A CSV file with a header row. | +| **JSON** | A JSON file holding an array of objects keyed by column name. | + +Pick **First Value** for a count or a sum: `SELECT count(*) FROM orders` hands the number straight +to **Calculate** or **Show Notification**. Pick **Rows** with **Repeat with Each** and **Get +Dictionary Value**. Every value arrives as text, NULL as `null` in JSON and as an empty field in +CSV, and binary as Base64. Two columns with the same name come back as `id` and `id 2`. + +**Row Limit** defaults to 500 and goes up to 10,000. A statement stops after 30 seconds. + +## What a shortcut may do + +The connection's **External Clients** level and [Safe Mode](/features/safe-mode) decide, exactly as +for [AppleScript](/developers/applescript#what-a-script-may-do). + +| Level on the connection | A shortcut may | +| --- | --- | +| Blocked | Nothing. The pickers leave it out, and a shortcut saved before it was blocked fails with *"External access is disabled for this connection"* | +| Read only | Read. A write, including **Add Row to Table**, fails with *"This connection is read only for external clients."* | +| Read & Write | Read and write, subject to Safe Mode | + +A statement that drops or truncates always asks first, in a TablePro dialog that names Shortcuts. +Under a Safe Mode that confirms writes, the insert actions ask once for the whole batch. Every +statement goes to the history drawer under **Shortcuts** and to the execution audit log. + +## Add rows + + + + In a new shortcut, add **Add Row to Table**. + + + Pick a **Connection**, then a **Table** read live from it. **Database or Schema** is optional and + lists schemas on PostgreSQL and the like, databases elsewhere; empty means the connection's own. + SQLite has neither, so it stays empty there. When the connection cannot open, both pickers + show why, such as an SSH host key to check, instead of an empty list. + + + Feed **Row (JSON or CSV)** from a Shortcuts **Dictionary** action keyed by column name, which + builds the row without typing JSON. **Add Rows to Table** has **Rows (JSON or CSV)** and a + **File** field instead. + + + It returns the number of rows inserted, ready for a later step, and speaks *"Added one row to + bookmarks."* + + + +On a Mac, rows go in the way a row added in the data grid does, so any engine whose grid adds rows +takes them. On iPhone and iPad, inserts work on MySQL, MariaDB, TiDB, OceanBase, PostgreSQL, +Redshift, SQL Server, SQLite, DuckDB and Oracle. An engine that cannot take them fails with +*"Redis connections do not support adding rows from Shortcuts."*, naming its own type. + +Siri takes "Open [connection] in TablePro", "Connect to [connection] in TablePro", "Add a row in +TablePro" and "Add rows in TablePro", with a connection name in place of the brackets. On a Mac it +also takes "Run a query in TablePro". + +## Data formats + +Keys match columns by name. A column you leave out stays out of the `INSERT` and takes its default, +and an empty or `null` primary key is dropped for the same reason, so auto-increment still fires. + +### JSON + +An object is one row; an array of objects is many, for **Add Rows to Table**. + +```json +{ "title": "TablePro docs", "url": "https://docs.tablepro.app", "tags": "reference" } +``` + +```json +[ + { "title": "First", "url": "https://example.com/1" }, + { "title": "Second", "url": "https://example.com/2" } +] +``` + +`null` inserts a SQL `NULL`, and numbers and booleans are inserted as text. Quote anything that has +to stay exact: a bare JSON number past 64-bit integer range is read as floating point and loses +digits, while `"18446744073709551615"` keeps every one. + +### CSV + +The first row is the header and names the columns. Quoting follows the usual rules. A file can be +UTF-8, UTF-16, Shift JIS, EUC-JP, GB 18030, Big5, EUC-KR or Windows-1252; the encoding is read +from the file. + +```text +title,url +First,https://example.com/1 +Second,https://example.com/2 +``` + +## Limits + +Up to 10,000 rows per run. **Add Rows to Table** runs the batch in one transaction wherever the +engine supports it, so a row that fails rolls back the whole batch instead of leaving half of it in. +On a Mac, an engine without transactions keeps the rows that went in before the failure, and the +error says how many. The action never joins a transaction that is already open: it stops instead. + +## When it refuses + +Nothing is inserted, except where the message says rows stay in. + +| Message | Cause | +| --- | --- | +| *"External access is disabled for this connection"* | The Mac connection's **External Clients** level is Blocked. | +| *"This connection is read only for external clients."* | The Mac connection's **External Clients** level is Read Only. | +| *"A transaction is open on this connection. Commit or roll it back in TablePro, then run the shortcut again."* | A query tab holds a transaction open on a Mac connection whose engine allows only one connection, such as DuckDB. | +| *"This connection's startup commands leave a transaction open…"* | A startup command such as `BEGIN` leaves a transaction open on the Mac connection. | +| *"…is read-only, so rows cannot be added."* | The iOS connection's safe mode blocks writes. A connection set to Confirm Writes asks first instead. | +| *"…has no column named …"* | A key in the data matches no column. | +| *"The data has no values to insert into …"* | Nothing in the data maps to a column. | +| *"No data was provided to add."* | Both the text field and the file were empty. | +| *"Line … of the file is not valid … text."* | That line holds bytes the file's encoding cannot read. | +| *"Too many rows. Add up to 10000 rows at a time."* | Over the cap. | +| *"Add Row to Table expects one row. Use Add Rows to Table for multiple rows."* | An array reached the single-row action. | +| *"…check the server's SSH host key first."* or *"…Open this connection in TablePro to check it."* | The SSH server is new, or its host key changed. A Shortcut has no screen to show the question on. | +| *"… of … statements were already written, and … cannot roll them back."* | A row failed on a Mac engine without transactions. The rows before it stay in, and running the shortcut again adds them a second time. | + +On iPhone and iPad the action also fails while the device is locked, because it reads the +connection's password from the Keychain. diff --git a/ios/index.mdx b/ios/index.mdx index d188377d..6a07cf08 100644 --- a/ios/index.mdx +++ b/ios/index.mdx @@ -286,6 +286,6 @@ A connection that uses an [SSH profile](/connections/ssh-profiles) on the Mac ar ## Shortcuts and widgets -Three App Intents put the app in Shortcuts, the Share Sheet, and Siri: **Open Connection**, **Add Row to Table**, **Add Rows to Table**. See [iOS Shortcuts](/integrations/ios-shortcuts) for pickers, data formats, and limits. +Three App Intents put the app in Shortcuts, the Share Sheet, and Siri: **Open Connection**, **Add Row to Table**, **Add Rows to Table**. See [Shortcuts](/integrations/shortcuts) for pickers, data formats, and limits. A **Quick Connect** home screen widget opens a saved connection directly and leaves out the ones that open on the Mac only. Handoff carries an open connection between devices. A `tablepro://connect/` link opens a connection and `tablepro://connect//table/` opens a table; the Mac's other links do less or nothing here, as [URL scheme](/developers/url-scheme#on-iphone-and-ipad) lists. A `.tablepro` file from Files or AirDrop imports its connections and saved queries.