Skip to content

feat(notebook): disable SQL cells without deleting their source - #1541

Open
shu-chen-dot-ca wants to merge 2 commits into
TabularisDB:mainfrom
shu-chen-dot-ca:feat-1510-disable-sql-cells
Open

shu-chen-dot-ca wants to merge 2 commits into
TabularisDB:mainfrom
shu-chen-dot-ca:feat-1510-disable-sql-cells

Conversation

@shu-chen-dot-ca

@shu-chen-dot-ca shu-chen-dot-ca commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1510.

Adds an enabled/disabled state to SQL notebook cells. A disabled cell keeps its source, configuration and last output, but nothing in the notebook sends it to the database until it is enabled again. That covers a direct run, Run All and automatic prerequisite resolution.

  • types/notebook.ts
    • Optional isDisabled on SQL cells and in the file format. Absent means enabled, so legacy cells and files load as enabled.
    • RunAllResult gains blocked and blockedCells. Each blocked cell lists the disabled cells it waits on.
  • utils/notebookRunAll.ts
    • getExecutableCells leaves disabled cells out; getDisabledCells lists them, so Run All counts them as skipped.
    • findDisabledPrerequisites(sql, cells, prepare) returns the disabled cells that stop a query: referenced directly, or through referenced cells that would have to run first because they have no current result. It resolves notebook parameters (so @source = {{cell_1}} counts) and handles reference cycles.
    • addBlocked records a blocked cell; formatRunAllSummary reports blocked cells.
  • utils/notebookVariables.ts: a disabled cell is never scheduled as a dependency, and its cached output is never substituted into a consumer's CTE (it stays an unresolved reference).
  • NotebookView.tsx
    • The run path returns at once for a disabled cell, whatever triggered it: the header button, the editor shortcut or a dependency.
    • It checks again after each lazy dependency run and on both sides of the query guard, which can wait on the dangerous-query confirmation. So a cell disabled while it waits is never sent: it stops with no error and Run All counts it as skipped.
    • A consumer of a disabled prerequisite is marked "Blocked: prerequisite {{cell_N}} is disabled" before any guard or execute_query call.
    • Run All re-reads each cell right before starting it. Blocked cells are counted separately: they are neither failures nor a reason to stop on error.
    • The in-flight result update only patches runtime fields, so a reply to a query sent before disabling cannot clear isDisabled. Disabling does not claim the query was cancelled.
    • No query plan is prepared for a disabled cell.
  • NotebookCellHeader.tsx / NotebookCellWrapper.tsx
    • A power toggle with aria-pressed, a translated aria-label/title ("Disable cell" / "Enable cell"), visible focus and theme tokens.
    • A "Disabled" badge. While disabled, the run button is disabled and labelled "This cell is disabled. Enable it to run it."
    • The query plan button stays in place but is disabled, so the header buttons don't shift under the pointer.
  • SqlCell.tsx
    • Keeps the plan section closed on disabled cells, since an open plan sends EXPLAIN (or EXPLAIN ANALYZE) as soon as it mounts.
    • Shows a status line on disabled cells. When an earlier result or error is still shown, it adds that the output is from an earlier run and is not current.
  • RunAllSummary.tsx: "N blocked", and for each blocked cell a link to it and to the disabled cell it waits on.
  • notebookFile.ts / notebookUndo.ts
    • isDisabled is written only when true, and read only from a literal true on SQL cells.
    • It is part of the undo signature, with "Disabled cell N" / "Enabled cell N" in the edit history.
    • Re-enabling is only a document change and executes nothing.
  • New strings in all 13 locales.

Out of scope, as the issue says: cancellation, scheduling and read-only enforcement. The SQL source export still includes disabled cells' SQL, since the issue only covers execution. Happy to leave them out or comment them out there if preferred.

Tests:

  • tests/utils/notebookRunAll.test.ts
    • Disabled and empty cells left out of Run All; legacy cells count as enabled.
    • Direct and transitive disabled prerequisites, with and without cached output; a chain stops at an enabled cell that already has a result.
    • Several disabled prerequisites reported once each, sorted; reference cycles terminate.
    • Markdown, missing and enabled cells ignored; parameter-made references counted.
    • Blocked counting and the summary text.
  • tests/utils/notebookFile.test.ts: round trip, enabled cells not written, legacy file loads as enabled, malformed values ("true", 1, null, {}) ignored, never set on Markdown.
  • tests/utils/notebookUndo.test.ts: signature change, describe disable/enable, undo/redo of a disable.
  • tests/utils/notebookVariables.test.ts: a disabled cell's cached output is not substituted, and a disabled cell is not scheduled as a dependency.
  • tests/components/notebook/NotebookView.test.tsx
    • Direct run: a disabled cell sends nothing and keeps its output.
    • Consumers of a disabled cell, with and without cached output, are blocked with no guard or query. So are the end of a dependency chain and a consumer whose reference comes from a parameter.
    • Disabled while waiting: a consumer disabled while its lazy dependency runs, and a cell disabled while the guard waits for confirmation, send nothing.
    • Run All with disabled, blocked, plain and chained cells sends only the plain query; the summary shows 1 succeeded, 1 skipped, 2 blocked with links to the disabled cell.
    • Run All edge cases:
      • Stop on error does not stop on a blocked cell.
      • Parallel cells are handled.
      • A cell disabled while earlier cells or the parallel group run is skipped.
      • A sequential consumer disabled during its own lazy dependency re-run is skipped, not failed or sent.
    • Re-enabling runs nothing, and undo/redo restore the flag.
    • A reply arriving after disabling keeps the cell disabled.
    • No plan is prepared for a disabled cell.
  • tests/components/notebook/NotebookCellWrapper.test.tsx, SqlCell.test.tsx and the new RunAllSummary.test.tsx: toggle name, state and handler; disabled run button with its reason; badge; disabled plan button with no EXPLAIN request; no toggle on Markdown; the notices; the summary links.

Validation:

  • pnpm typecheck && pnpm lint && pnpm format:check && pnpm web:boundaries && pnpm web:packaging && pnpm web:docs && pnpm web:manual-parity && pnpm test:contrast && pnpm build && pnpm test run --maxWorkers=4: all passed (565 files, 9125 tests). No Rust changes.
  • GitNexus upstream impact:
    • serializeNotebook HIGH: it is the save path of every notebook (create, rename, import); the change there is one optional field written only when true.
    • NotebookCellHeader, documentSignature, deserializeNotebook and runCellInner LOW.
    • getExecutableCells, findUnresolvedDependencies and describeChange have no resolved callers in the index; text search shows they are used only in NotebookView and NotebookHistoryPanel.
  • detect-changes before each commit: notebook symbols only. Risk is high because NotebookView is in many flows; the export handlers it lists only moved down the file.
  • Manual check in Tabularis Web (nightly binary serving this branch's build) with a SQLite connection and a two-cell notebook where cell 2 reads {{cell_1}}:
    • A notebook saved before the change opened with both cells enabled.
    • After disabling cell 1, Run All reported "1 skipped, 1 blocked" with links, and cell 2 showed the blocked message.
    • The state survived a reload.
    • The server's audit log showed no execute_query after disabling, including after re-enabling.
Before After
before after

Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

@kilo-code-bot

kilo-code-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

I found no defects in the new commit 355fab19, which re-checks a cell's disabled state before its query is sent. I read its diff and the surrounding code in NotebookView.tsx. I did not run the tests.

  • The disabled-state re-checks sit in the right places: after dependency runs and on both sides of the query guard's confirmation.
  • A cell that is disabled mid-run is recorded as skipped in run-all.
  • A rejected sequential run is now recorded as a failure instead of aborting the whole run.
  • The other files in the incremental range come from the base branch, not from this PR's changes.
Files Reviewed (2 files)
  • packages/web-ui/src/components/notebook/NotebookView.tsx
  • packages/web-ui/tests/components/notebook/NotebookView.test.tsx
Previous Review Summary (commit a3b1b9a)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit a3b1b9a)

Status: No Issues Found | Recommendation: Merge

I found no defects in the changed code. I read the diff and the saved patch output for the source files. I did not run the tests, and I did not read the changes under packages/web-ui/src/i18n/locales/ or packages/web-ui/src/types/notebook.ts in detail.

Files Reviewed (31 files)
  • packages/web-ui/src/components/notebook/NotebookCellHeader.tsx
  • packages/web-ui/src/components/notebook/NotebookCellWrapper.tsx
  • packages/web-ui/src/components/notebook/NotebookView.tsx
  • packages/web-ui/src/components/notebook/RunAllSummary.tsx
  • packages/web-ui/src/components/notebook/SqlCell.tsx
  • packages/web-ui/src/i18n/locales/*.json (13 locale files)
  • packages/web-ui/src/types/notebook.ts
  • packages/web-ui/src/utils/notebookFile.ts
  • packages/web-ui/src/utils/notebookRunAll.ts
  • packages/web-ui/src/utils/notebookUndo.ts
  • packages/web-ui/src/utils/notebookVariables.ts
  • packages/web-ui/tests/** (8 test files)

Reviewed by claude-sonnet-5.5 · Input: 248 · Output: 1.1K · Cached: 194.9K

Review guidance: REVIEW.md from base branch main

@shu-chen-dot-ca
shu-chen-dot-ca force-pushed the feat-1510-disable-sql-cells branch from a3b1b9a to 355fab1 Compare November 13, 2026 17:05
@shu-chen-dot-ca

Copy link
Copy Markdown
Contributor Author

Rebased onto main (5725dad) to resolve the conflict. The only conflict was in utils/notebookUndo.ts, which git treats as binary because of the raw NUL separator in describeChange. It is now a text merge that keeps both sides: main's kpiConfig in the undo signature and the kpiCell change kind, plus this PR's isDisabled / disableCell / enableCell. The NUL bytes are unchanged. Everything else applied cleanly. Full frontend checks pass again (578 files, 9492 tests).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: Notebooks: disable SQL cells without deleting their source

1 participant