Skip to content

CodeMirror stack 2/4: rich schema autocomplete, /-/editor-schema.json, defaultTable#2835

Draft
asg017 wants to merge 6 commits into
asg017/codemirror-1-upgradefrom
asg017/codemirror-2-schema
Draft

CodeMirror stack 2/4: rich schema autocomplete, /-/editor-schema.json, defaultTable#2835
asg017 wants to merge 6 commits into
asg017/codemirror-1-upgradefrom
asg017/codemirror-2-schema

Conversation

@asg017

@asg017 asg017 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Part 2 of the CodeMirror stack (integration view: #2833). Takes full advantage of lang-sql's schema autocomplete, server side.

What

  • Rich completions (_editor_schema() in query_helpers.py): columns are now lang-sql Completion objects carrying their SQLite type as popup detail and a boost that ranks them above bare keywords. Views are {self, children} containers labelled "view" and — new — carry their real columns via PRAGMA table_xinfo (they previously completed with nothing). The old flat _table_columns() is kept untouched for the write-template path.
  • GET /{database}/-/editor-schema.json: machine-readable schema for SQL-editor consumers (the embeddable editor in part 3/4 of this stack, external tools like datasette-paper). Neutral shape — {"database", "tables": [{"name", "view", "columns": [{"name", "type"}]}]} — deliberately not coupled to CodeMirror's config format. Gated on both view-database and execute-sql (same permissions as the inline editor schema); view-database is checked before database existence so non-viewers can't probe; a 403 leaks zero table names; hidden tables (FTS shadow tables etc.) excluded. Named editor-schema.json because /-/schema.json is the existing DDL endpoint — docs cross-link the two.
  • defaultTable: the table page's "View and edit SQL" link now carries ?_table=<name>; QueryView validates it against the actor-visible tables/views before exposing it, so that table's columns complete unprefixed on the query page. Stored/canned queries unaffected; arbitrary ?_table= values are dropped, not reflected.
  • window.editor.updateSchema({schema, defaultTable}): the sql() extension now lives in a per-editor Compartment, so long-lived pages and plugins can refresh autocomplete after DDL.

Review focus

The endpoint's permission gating is the crux — see DatabaseEditorSchemaView in views/special.py and the no-leak tests in tests/test_schema_endpoints.py.

Note: the table_columns key in the database JSON context now carries the richer shape (shared call site) — flagging in case that field is considered public API surface.

Testing

New tests: payload shape, endpoint allowed/denied/hidden/view cases, _table= validation and non-reflection. Full suite green (2304 passed).

The stack

# PR Content
1/4 #2834 CM 6.x upgrade, option-name bugfix, rollup build
2/4 #2835 Rich schema autocomplete, /-/editor-schema.json, defaultTable
3/4 #2836 datasette-sql-editor ESM primitives
4/4 #2837 <datasette-sql-editor> element + core-page dogfood

Each PR is based on the previous branch; merge top-down, retargeting the next base to main as each lands. Bundle files (*.bundle.js) conflict on rebase by nature — resolve by re-running npm run build:codemirror, never by merging. Integration view of the whole branch: #2833.

🤖 Generated with Claude Code

asg017 and others added 6 commits July 10, 2026 10:46
_editor_schema() emits lang-sql Completion objects (column type as
detail, boost above keywords) and gives views their real columns via
PRAGMA table_xinfo in a self/children container labelled 'view'.
_table_columns() is unchanged for the write-template path. Note the
table_columns field in the database JSON context now carries this
richer shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per-view Compartment wraps the sql() extension; window.editor.updateSchema(
{schema, defaultTable, defaultSchema}) reconfigures autocomplete live.
Declares @codemirror/state as a direct dependency since it is now
imported directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Neutral {database, tables: [{name, view, columns: [{name, type}]}]}
shape, gated on view-database + execute-sql with no table-name leak on
403, hidden tables excluded. /-/schema.json was already taken by the
DDL endpoint, hence editor-schema.json. _editor_schema() now maps from
the shared _schema_tables() introspection helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The table page's 'View and edit SQL' link now carries ?_table=<name>;
QueryView validates it against the actor-visible tables/views for the
database before exposing it as default_table, so the editor completes
that table's columns unprefixed. Stored/canned queries are unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follow-up to d12f0d2: the test regexes the inlined schema= JS and
still asserted the old flat list-of-strings shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant