The context
When a user opens a table in a database client, the first thing they try to do is often to fix a value in place. A mistyped email, a flag to toggle, a note to add. Opening a SQL tab, writing the UPDATE clause with the right WHERE, running it, coming back. That's what most desktop clients require, and it's disproportionate for a one-character change.
The Inline Edit of QoreDB's Data Grid addresses this precise case: double-click a cell, you type, you confirm, and the row is written to the database. All without leaving the grid, without building the query by hand, and without hiding what happens on the server side.
How a cell becomes editable
Entering edit mode is handled by the useInlineEdit hook. This hook centralizes the editing state (current cell, typed value, original value, full row) and exposes the callbacks used by the grid: startInlineEdit, commitInlineEdit, cancelInlineEdit.
Before opening the input, startInlineEdit validates three things. The context: it needs a sessionId, a namespace, and a table name. The primary key: without a PK, no safe WHERE can be built, editing is refused, and the user sees an explicit message (grid.updateNoPrimaryKey). The environment and the driver: if the connection is read-only or the driver doesn't support mutations (Redis, for example), editing is blocked before the field is even displayed.
This check happens on the client side, which avoids flashing an input only to end up on a backend error. The rule is simple: if editing isn't possible, the cell never becomes editable.
Validating and converting what the user typed
The input is a text field. What comes out of it isn't directly a SQL value. A user who types 42 in an INTEGER column wants an integer. Someone who types null in a nullable column wants NULL. Someone who types {"key": 1} in a jsonb column wants JSON.
The conversion is done in useValueParsing, based on the column type reported by the driver. Booleans accept true and false case-insensitively. Numeric types (int, numeric, float, serial) go through Number() with a fallback to the raw string if the parse fails, so that the database rejects the value with its own error message rather than inventing a silent conversion. The word null (a literal, case-insensitive) is translated to SQL NULL. JSON is parsed and re-serialized by the driver on the Rust side.
The principle is to guess nothing on the engine's behalf. QoreDB does a minimal, readable conversion, and if the database refuses the value, the error surfaced is the engine's, not one dressed up by the client.
What is sent to the database
Once the value is validated, the hook calls the Tauri command updateRow. This command takes the session_id, the namespace, the table name, the primary key (in the form of RowData), and the modified columns (also as RowData). It goes through the mutation preflight (safety warning, environment check, logging in the interceptor), then delegates to the driver.
Each driver translates the mutation into its own dialect. On PostgreSQL, MySQL, SQL Server, or SQLite, it's an UPDATE table SET col = $1 WHERE pk = $2 with parameterized bindings, never string concatenation. On MongoDB, it's an updateOne with a filter built from the primary key and a $set operator on the modified fields. The driver stays native; there's no ORM or intermediate layer inventing a universal syntax.
The primary key is the one reported by the engine's metadata at the time of schema inspection. No FK reconstructed on the client side, no heuristic on columns that "look like" an ID. If the database doesn't declare a primary key, editing is refused.
Environments change the behavior
QoreDB distinguishes three environments per connection: development, staging, production. The inline edit hook takes this into account at commit time. In dev, the UPDATE goes out immediately. In staging or production, a confirmation dialog intercepts the mutation before it's sent to the database.
This dialog makes visible what's about to happen: the table, the row's primary key, the column, the value before and the value after. The confirmation click activates the acknowledged_dangerous flag that the backend command expects in order to authorize the mutation. This double barrier is the same one used for mutations executed from the SQL editor; the logic isn't duplicated in the grid.
Sandbox Mode: editing without writing
When Sandbox Mode is active on a connection, inline edit no longer talks to the database. It stacks the modification in a local annotation layer, with the old value and the new one. The user sees the updated cell in the grid with a visual marker indicating that it's a pending change.
The hook detects this mode via sandboxMode and calls onSandboxUpdate(pk, oldValues, newValues) instead of updateRow. No network, no Rust command triggered, the database is never touched. It's the same mechanism that feeds the Sandbox: the changes can then be exported as SQL, replayed, or discarded entirely.
What inline edit does not do
The scope is deliberately narrow. Only one cell is modified per commit. No batch editing from the grid, no multi-select with a single value, no formula dragged from one cell to another. A user who wants to modify hundreds of rows opens the SQL editor and writes their query; it's clearer and faster than simulating it in a UI.
Likewise, inline edit doesn't try to resolve a foreign key constraint on its own. If the broken value is an FK, the database returns its error, which is shown in a toast. This is consistent with the rest of the product: QoreDB makes visible what the engine does; it doesn't substitute its own validation for the database's.
What it looks like in practice
A developer inspecting a PostgreSQL table double-clicks an email cell, fixes it, presses Enter. A dialog appears if the connection is marked production, otherwise the update goes out directly. The grid refreshes the row. The command left a trace in the interceptor (for time-travel if enabled on the table) and in the logs. The driver executed a parameterized UPDATE targeting the row's primary key.
On MongoDB, the same sequence produces an updateOne targeting the document's _id, with a $set on the modified field. The grid doesn't distinguish between the two engines on the UX side: it's the lower layers that translate the mutation into the database's native semantics.
Why this form
Editing a cell is one of the most frequent operations in a database client, and one of the easiest to implement badly. A client that builds an UPDATE over all displayed columns can overwrite values modified by another process. A client that guesses the primary key can target the wrong row. A client that validates on the frontend can refuse a value the database would have accepted, or the reverse.
QoreDB's implementation rests on three rules: the primary key comes from the engine, the mutation targets only the modified column, and type conversion is minimal and lets the database arbitrate. It's not the product's most visible feature, but it's the one that has to be the hardest to break.
Stay updated on new releases
Subscribe to get product releases, new drivers notifications, and technical tutorials.

