> ## 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.

# Change Tracking

> Queue cell edits, row inserts, and deletions locally before committing to the database

# Change Tracking

Changes in TablePro are queued in memory, not applied immediately. Edit cells, insert rows, delete rows, then review everything before committing. Nothing touches the database until you say so.

<Frame caption="Data grid with pending changes highlighted">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-tracking.png" alt="Change Tracking" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-tracking-dark.png" alt="Change Tracking" />
</Frame>

<Tip>
  Change tracking is per-tab. Switching tabs preserves your edits.
</Tip>

## Data Changes

TablePro tracks three types of data changes: cell edits, row insertions, and row deletions.

### Editing Cells

Double-click any cell to edit (see [Data Grid](/features/data-grid)). Changes queue immediately.

<Frame caption="Modified cells are highlighted">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-tracking-modified.png" alt="Modified cells" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-tracking-modified-dark.png" alt="Modified cells" />
</Frame>

<Note>
  Changing a value back to its original automatically removes it from the queue.
</Note>

### Adding Rows

To insert a new row:

1. Click the **+** button in the toolbar or use the keyboard shortcut
2. A new row appears at the bottom of the data grid, marked with an insertion indicator
3. Fill in the values for each column
4. Columns with default values are pre-filled with `DEFAULT`

Edits to cells in a new row are folded into the insertion, not tracked as separate updates.

<Frame caption="Newly added row">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-new-row.png" alt="Newly added row with insertion indicator" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-new-row-dark.png" alt="Newly added row with insertion indicator" />
</Frame>

### Deleting Rows

Select rows and press `Delete`. Deleted rows show a strikethrough indicator and stay visible until commit or discard.

<Frame caption="Deleted row">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-deleted-row.png" alt="Deleted row with deletion indicator" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/change-deleted-row-dark.png" alt="Deleted row with deletion indicator" />
</Frame>

<Warning>
  Batch deletion of multiple rows is tracked as a single undo action. Undoing a batch deletion restores all rows at once.
</Warning>

## Commit & Discard

### Committing Changes

Click **Commit** or press `Cmd+S`. TablePro generates parameterized SQL, executes it, clears the queue, and refreshes the grid.

Generated SQL:

| Change Type   | SQL Generated                            |
| ------------- | ---------------------------------------- |
| Cell edit     | `UPDATE ... SET column = ? WHERE pk = ?` |
| Row insertion | `INSERT INTO ... (columns) VALUES (?)`   |
| Row deletion  | `DELETE FROM ... WHERE pk = ?`           |

<Note>
  UPDATE statements require a primary key on the table. If no primary key is defined, TablePro shows an error when you try to commit updates. DELETE statements can work without a primary key by matching all column values.
</Note>

### Discarding Changes

Click **Discard** to revert all pending changes and clear the undo/redo stack.

### Previewing Data SQL

Click the **Preview SQL** button (eye icon) or press `Cmd+Shift+P` to see the exact SQL before committing. Use **Copy All** to copy to clipboard.

<Tip>
  The preview inlines parameter values so you can verify exactly what will run. Destructive operations are highlighted with a warning banner.
</Tip>

<Frame caption="Commit and Discard buttons with pending changes count">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/commit-discard-buttons.png" alt="Commit and Discard buttons with pending changes count" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/commit-discard-buttons-dark.png" alt="Commit and Discard buttons with pending changes count" />
</Frame>

## Undo & Redo

| Action | Shortcut      |
| ------ | ------------- |
| Undo   | `Cmd+Z`       |
| Redo   | `Cmd+Shift+Z` |

<Tip>
  Context-aware: `Cmd+Z` undoes text edits when the SQL editor is focused, data changes when the grid is focused.
</Tip>

Stacks are per-tab. Committing or discarding clears both stacks.

## Schema Changes

Table structure changes (columns, indexes, foreign keys) use the same queue-based approach.

### Tracked Schema Operations

| Operation              | What Is Tracked                                             |
| ---------------------- | ----------------------------------------------------------- |
| **Add column**         | New column definition (name, type, nullable, default, etc.) |
| **Modify column**      | Old and new column definitions                              |
| **Delete column**      | Column marked for removal                                   |
| **Add index**          | New index definition (name, columns, type, uniqueness)      |
| **Modify index**       | Old and new index definitions                               |
| **Delete index**       | Index marked for removal                                    |
| **Add foreign key**    | New FK definition (columns, references, actions)            |
| **Modify foreign key** | Old and new FK definitions                                  |
| **Delete foreign key** | FK marked for removal                                       |
| **Modify primary key** | Old and new primary key columns                             |

### Visual Indicators

* **New items**: highlighted with an insertion color
* **Modified items**: changed fields are marked
* **Deleted items**: shown with a deletion indicator

<Frame caption="Schema changes highlighted in Structure tab">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/schema-change-indicators.png" alt="Schema changes highlighted in Structure tab" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/schema-change-indicators-dark.png" alt="Schema changes highlighted in Structure tab" />
</Frame>

## Previewing Schema SQL

Before applying schema changes, preview the generated SQL:

Make your changes in the Structure tab, then click **Commit** (`Cmd+S`). A preview sheet shows the ALTER TABLE statements. Click **Apply Changes** to execute or **Cancel** to go back.

<Frame caption="Schema change preview with generated SQL">
  <img className="block dark:hidden" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/schema-preview.png" alt="Schema Preview" />

  <img className="hidden dark:block" src="https://mintlify.s3.us-west-1.amazonaws.com/ngquct/images/schema-preview-dark.png" alt="Schema Preview" />
</Frame>

<Tip>
  Copy individual SQL statements from the preview sheet using the copy button next to each statement.
</Tip>

## SQL Generation

Data changes use parameterized statements. Schema changes produce database-specific ALTER TABLE statements:

<Tabs>
  <Tab title="MySQL/MariaDB">
    ```sql theme={null}
    UPDATE `users` SET `name` = ? WHERE `id` = ? LIMIT 1
    INSERT INTO `users` (`name`, `email`) VALUES (?, ?)
    DELETE FROM `users` WHERE `id` = ? OR `id` = ?

    ALTER TABLE `users` ADD COLUMN `phone` VARCHAR(20) NOT NULL
    ALTER TABLE `users` MODIFY COLUMN `name` VARCHAR(200) NOT NULL
    ```
  </Tab>

  <Tab title="PostgreSQL">
    ```sql theme={null}
    UPDATE "users" SET "name" = $1 WHERE "id" = $2
    INSERT INTO "users" ("name", "email") VALUES ($1, $2)
    DELETE FROM "users" WHERE "id" = $1 OR "id" = $2

    ALTER TABLE "users" ADD COLUMN "phone" VARCHAR(20) NOT NULL
    ALTER TABLE "users" ALTER COLUMN "name" TYPE VARCHAR(200)
    ```
  </Tab>

  <Tab title="SQLite">
    ```sql theme={null}
    UPDATE "users" SET "name" = ? WHERE "id" = ?
    INSERT INTO "users" ("name", "email") VALUES (?, ?)
    DELETE FROM "users" WHERE "id" = ?

    ALTER TABLE "users" ADD COLUMN "phone" TEXT
    CREATE INDEX "idx_email" ON "users" ("email")
    ```

    <Warning>
      SQLite has limited ALTER TABLE support. Use the SQL editor for modifications that require table recreation.
    </Warning>
  </Tab>
</Tabs>
