> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tablepro.app/llms.txt
> Use this file to discover all available pages before exploring further.

# SQL Editor

> Tree-sitter syntax highlighting, multi-statement execution, Vim mode, and built-in SQL formatting

# SQL Editor

Write and run SQL with tree-sitter-powered syntax highlighting, schema-aware autocomplete, and multi-statement execution in a single editor pane.

<Frame caption="SQL Editor with syntax highlighting">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/sql-editor.png" alt="SQL Editor" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/sql-editor-dark.png" alt="SQL Editor" />
</Frame>

## Writing Queries

### Multiple Queries

Separate multiple queries with semicolons:

```sql theme={null}
SELECT * FROM users LIMIT 10;
SELECT COUNT(*) FROM orders;
SELECT name, email FROM customers WHERE country = 'US';
```

Place your cursor in any statement and press `Cmd+Enter` to execute just that one.

### Selecting and Executing

Select text and press `Cmd+Enter` to run only the selection. Multiple statements in the selection run sequentially in a transaction:

* If any statement fails, execution stops and all changes roll back
* The error identifies which statement failed (e.g., "Statement 3/5 failed: ...")
* The last `SELECT` result appears in the data grid
* Each statement is recorded individually in query history

```sql theme={null}
DROP TABLE IF EXISTS users;
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100));
INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');
SELECT * FROM users;
```

<Frame caption="Executing multiple SQL statements">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/multi-statement-execution.png" alt="Multi-statement execution" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/multi-statement-execution-dark.png" alt="Multi-statement execution" />
</Frame>

## Autocomplete

Autocomplete appears as you type. See [Autocomplete](/features/autocomplete) for details.

<Frame caption="SQL autocomplete">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/autocomplete-popup.png" alt="Autocomplete" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/autocomplete-popup-dark.png" alt="Autocomplete" />
</Frame>

### Context-Aware Suggestions

| Context               | Suggestions                            |
| --------------------- | -------------------------------------- |
| After `SELECT`        | Column names, `*`, functions           |
| After `FROM` / `JOIN` | Table names, schema names              |
| After `WHERE`         | Column names from selected tables      |
| After `.` (dot)       | Columns from the specified table/alias |
| Start of statement    | SQL keywords                           |

Table aliases are resolved automatically: typing `u.` after `FROM users u` shows columns from `users`.

### Keyword Suggestions

Keywords are context-sensitive:

* After `SELECT`: `DISTINCT`, `TOP`, `ALL`
* After `FROM`: `JOIN`, `LEFT JOIN`, `INNER JOIN`, `WHERE`
* After `WHERE`: `AND`, `OR`, `NOT`, `IN`, `LIKE`, `BETWEEN`

## Query Parameters

Use `:name` placeholders instead of hardcoding values. Press `Cmd+Enter`, fill in the parameter panel, execute again. Values are bound via prepared statements.

```sql theme={null}
SELECT * FROM users WHERE id = :user_id AND status = :status;
```

See [Query Parameters](/features/query-parameters) for details.

## Query Execution

### Running Queries

| Action        | Shortcut       | Description                                      |
| ------------- | -------------- | ------------------------------------------------ |
| Execute query | `Cmd+Enter`    | Runs query at cursor, or all selected statements |
| Cancel query  | `Cmd+.`        | Stops the running query                          |
| Explain query | `Option+Cmd+E` | Show the execution plan for the query at cursor  |
| Format query  | `Cmd+Shift+L`  | Format the current query for readability         |

### Query Results

Results appear in the data grid below the editor with row count and execution time. Large result sets are paginated.

#### Clearing Results

The trash button in the editor toolbar clears the query and its results together. To clear results but keep the query, right-click the results and choose **Clear Results**. Running a query again repopulates the panel.

#### Collapsible Results Panel

Toggle the results panel with `Cmd+Opt+R` or the toolbar button to give the editor full height. The panel auto-expands when a new query executes.

#### Multiple Result Tabs

When running multiple statements separated by `;`, each statement produces its own result tab. Switch between tabs by clicking or with `Cmd+Opt+[` / `Cmd+Opt+]`. Close a result tab with `Cmd+Shift+W`.

#### Pinning Results

Right-click a result tab and select **Pin Result** to preserve it from being overwritten on the next query execution. Pinned tabs stay until explicitly unpinned or closed.

#### Inline Errors

Query errors display as a red banner directly above the results area, showing the database error message. Dismiss with the close button.

#### Non-SELECT Queries

INSERT, UPDATE, DELETE, and DDL statements show a compact success view with affected row count and execution time instead of an empty grid.

### Explain Query

Press `Option+Cmd+E` to view the execution plan. Shows index usage, join strategies, and estimated row counts. TablePro uses the correct syntax per database (`EXPLAIN` for MySQL/PostgreSQL, `EXPLAIN QUERY PLAN` for SQLite).

<Tip>
  Run Explain before expensive queries to verify index usage.
</Tip>

<Frame caption="EXPLAIN query execution plan">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/explain-query-result.png" alt="EXPLAIN query execution plan" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/explain-query-result-dark.png" alt="EXPLAIN query execution plan" />
</Frame>

## SQL Formatting

Press `Cmd+Shift+L` to format the current query. You can also click **Format** in the toolbar or use **Query** > **Format Query**. The shortcut is rebindable in **Settings** > **Keyboard**.

TablePro ships a token-based formatter (rewritten in v0.34.0). It parses the query into tokens before reflowing, so it handles:

* JOINs (INNER, LEFT, RIGHT, FULL, CROSS, LATERAL)
* Subqueries and derived tables
* CASE expressions
* Common Table Expressions (CTEs), including recursive
* Window functions (`OVER (...)`)
* 15+ other SQL constructs (UNION, INTERSECT, EXCEPT, GROUP BY, HAVING, etc.)

The formatter also:

* Adds line breaks per clause (`SELECT`, `FROM`, `WHERE`, `JOIN`)
* Indents logically with consistent spacing
* Preserves comments, string literals, and cursor position
* Detects your database dialect and preserves backtick (MySQL) or double-quote (PostgreSQL) identifiers
* Preserves the original keyword case by default. Toggle uppercase/lowercase keyword output in **Settings** > **Editor**

### Limitations

The formatter handles pure SQL only. Procedural extensions (PL/pgSQL `DO` blocks, MySQL stored procedures, T-SQL `BEGIN`/`END` blocks) are passed through with minimal changes.

### Example

**Before**:

```sql theme={null}
select u.id,u.name,count(o.id) as order_count from users u left join orders o on u.id=o.user_id where u.status='active' group by u.id,u.name having count(o.id)>5 order by order_count desc;
```

**After**:

```sql theme={null}
SELECT
    u.id,
    u.name,
    COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.status = 'active'
GROUP BY u.id, u.name
HAVING COUNT(o.id) > 5
ORDER BY order_count DESC;
```

<Frame caption="SQL query before and after formatting">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/sql-format-result.png" alt="SQL query before and after formatting" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/sql-format-result-dark.png" alt="SQL query before and after formatting" />
</Frame>

## Vim Mode

Enable Vim keybindings in **Settings** > **Editor** > **Vim mode**. Supports Normal, Insert, Visual, and Command-line modes.

Key mappings:

| Action                | Keys               |
| --------------------- | ------------------ |
| Execute query         | `:w`               |
| Close tab             | `:q`               |
| Enter Insert mode     | `i`, `a`, `o`, `O` |
| Return to Normal mode | `Escape`           |
| Delete word           | `dw`               |
| Delete line           | `dd`               |
| Yank (copy) line      | `yy`               |
| Paste                 | `p`                |
| Visual select         | `v` + motion       |
| Go to line 10         | `:10`              |
| Search forward        | `/pattern`         |
| Search backward       | `?pattern`         |
| Next match            | `n`                |
| Previous match        | `N`                |
| Undo                  | `u`                |
| Redo                  | `Ctrl+R`           |

Standard motions (`h/j/k/l`, `w/b/e`, `0/$`, `gg/G`), operators (`d`, `c`, `y`), and count prefixes (`3dd`, `5j`) all work as expected. Text objects like `ciw` (change inner word) and `di"` (delete inside quotes) are supported.

<Tip>
  Use `:w` to execute queries.
</Tip>

## Editor Settings

Customize font, line numbers, word wrap, Vim mode, and indentation in **Settings** > **Editor**.

Editor windows remember their size, position, and zoom state between launches. See [Query Tabs](/features/tabs#window-size-position-and-zoom) for details.

## AI Assistance

Use **Explain with AI** (`Cmd+L`) to understand queries, **Optimize with AI** (`Cmd+Option+L`) for performance suggestions, or click "Ask AI to Fix" in error dialogs. See [AI Assistant](/features/ai-assistant) for configuration.

## SQL Files

### Opening Files

Open `.sql` files in three ways:

* Double-click a `.sql` file in Finder (or **Open With** > **TablePro**)
* **File** > **Open File...** (`Cmd+O`) to pick files via a dialog
* Drag `.sql` files onto the TablePro dock icon

Files open in a new tab. If not connected to a database, they're queued and open automatically on connect. Opening the same file twice focuses the existing tab instead of creating a duplicate.

### Saving Files

* **`Cmd+S`** saves the current query back to the source file
* **`Cmd+Shift+S`** opens a **Save As** dialog to save as a new `.sql` file
* For untitled query tabs (no file), `Cmd+S` triggers Save As automatically

The title bar shows the filename for file-backed tabs. A dot appears on the close button when there are unsaved changes (standard macOS behavior). `Cmd+click` the filename in the title bar to reveal the file in Finder.

<Note>
  When a tab has both unsaved file changes and pending data grid edits, `Cmd+S` saves the data grid changes first. Save the file after the grid save completes.
</Note>

### External modifications

If a file changes on disk while it's open in TablePro (a `git pull`, an edit in VS Code, etc.), a yellow banner appears above the editor with a one-click **Reload from Disk**. Reload pulls the new content in and discards your tab edits.

If you save (`Cmd+S`) while the file has changed externally, TablePro shows a side-by-side diff sheet with line-level highlighting and three actions:

* **Keep My Changes** writes your tab content back, overwriting the external edits.
* **Reload from Disk** drops your edits and loads the external version.
* **Cancel** closes the sheet without saving so you can copy parts out manually.

### Linked folders

For watching a whole folder of `.sql` files (e.g., a Git repo of team queries), use [Linked SQL Folders](/features/favorites#linked-sql-folders) instead of opening each file by hand. Linked folders update the sidebar within a second of any on-disk change.
