74 KiB
基于 DBX 的 Navop SQL 编辑器完整实现规格
文档状态:Implementation Specification
目标读者:负责 Navop SQL 编辑器、SQL 分析、元数据、执行链路和 GPUI Input 基础设施的开发 Agent
基准源码:本工作区
dbx与navop当前源码编写日期:2026-08-27
目标:以 DBX 的真实源码行为为基线,在 Navop 中实现一套统一、可扩展、异步安全的 SQL 编辑器能力
1. 文档目的
本文不是 UI 效果猜测,也不是只描述“行号左侧放一个运行按钮”的局部需求。本文依据 DBX 当前源码,对 SQL 编辑器的完整能力、内部数据流、边界行为、异步约束和测试基线进行拆解,并给出 Navop(Rust + GPUI)的迁移设计。
其他 Agent 应能依据本文按阶段完成以下能力:
- 在每条完整、可执行 SQL statement 的起始行左侧显示运行图标;
- 点击图标精确执行该 statement,不改变当前光标或选区;
- hover 表、视图、函数等 SQL 对象时展示详细元数据和 DDL;
- 提供表、字段、别名、CTE、函数、关键字、snippet 等上下文补全;
- 提供当前 statement 边框、执行状态 marker、错误映射和结果联动;
- 提供语义诊断、格式化、参数替换、变量展开、
IN (...)粘贴、INSERT 值提示等编辑辅助; - 正确处理不同数据库方言、quoted identifier、大 schema 和 stale async response;
- 建立统一的 statement、document revision、metadata scope 和 offset contract,避免各模块独立解析 SQL。
1.1 非目标
本文不要求:
- 将 DBX 的 Vue/CodeMirror 代码逐行翻译为 Rust;
- 在一个 PR 中一次性完成所有能力;
- 将展示型 fallback DDL 当作可直接执行的权威 DDL;
- 用
StreamingSqlParser直接承担编辑器增量分析; - 为实现 SQL 专用功能而破坏 GPUI Input 的通用性。
1.2 事实与建议的标记
本文使用以下措辞区分来源:
- DBX 事实:DBX 当前源码已经存在的行为;
- Navop 现状:Navop 当前源码已经具备的能力;
- Navop 方案:建议新增或改造的实现;
- 建议扩展:不一定与 DBX 完全等价,但为了 Navop 架构完整性建议实现。
2. 总体结论
DBX SQL 编辑器不是一个单独的“编辑框组件”,而是下列子系统的组合:
长期存活的编辑器状态
│
├── SQL statement range / executable range
├── dialect-aware lexical + semantic analysis
├── local metadata cache + remote metadata assistant
├── completion / signature / snippets
├── hover / navigation / context actions
├── diagnostics / execution error mapping
├── gutter / current-statement frame / decorations
├── execution target resolution / parameter preprocessing
├── result run / source range / execution state
└── formatter / editing assists / persistence
Navop 实现时必须坚持三个核心原则。
2.1 唯一 statement range 来源
以下所有能力必须共用同一份 SqlStatementRangeService 或 SqlAnalysisSnapshot.statements:
- gutter 图标位置;
- gutter 点击执行范围;
- Run Current;
- current statement frame;
- execution picker;
- diagnostics statement window;
- execution marker;
- database error line/column 回映;
- result statement source range。
禁止 gutter、编辑器命令、driver execution parser、diagnostics 各自采用不同的 SQL 分割算法。
2.2 所有异步结果必须绑定 revision 和 scope
每一个异步请求至少绑定:
- document revision;
- connection id;
- catalog/database/schema;
- database type/dialect;
- metadata generation;
- request id 或 cancellation token。
请求返回后,如果其中任何一项已变化,结果必须丢弃,且不得写入当前 cache。
2.3 SQL 能力与 GPUI Input 基础能力分层
建议分为三层:
crates/ui
通用 gutter marker、range decoration、hover/completion host、hitbox、绘制
crates/db
SQL tokenizer、statement ranges、identifier、semantic model、diagnostics contracts
crates/db_view
connection scope、metadata provider、execution、result integration、SQL editor facade
GPUI Input 不应知道“table”或“SQL statement”,但应知道:
- 某逻辑行有一个可点击 marker;
- 某 byte/rope range 有 decoration;
- 某 marker 有图标、状态、tooltip 和 action;
- 某异步结果属于哪个 document revision。
3. DBX 能力总览
| 能力 | DBX 当前行为 | Navop 目标 |
|---|---|---|
| Statement 分割 | 方言感知,支持 ;、GO、DELIMITER、Oracle /、routine block 等 |
建立编辑器专用 range engine |
| 左侧运行图标 | 每条 executable statement 起始行显示 | 增加通用 gutter marker lane |
| 精确执行 | gutter 永远执行对应 statement | 统一 ExactRange execution target |
| 当前 statement | 光标与前后空白、分号、注释有明确归属规则 | 与 gutter 使用相同 snapshot |
| 当前 statement frame | 无非空选区时绘制 statement 边框 | 增加 range decoration/layer |
| 表/字段补全 | semantic + metadata + keyword + snippet 合并 | 扩展当前 provider 为多 source |
| CTE/子查询补全 | 可使用局部推导出的输出列 | 扩展 symbol/semantic model |
| 函数补全与签名 | routine、signature、parameter help | 元数据增加 overload/signature |
| Hover | 表结构、注释、列、PK、索引、DDL | SQL hover resolver + detail popover |
| Navigation | table/view/materialized view/routine 等 | Cmd/Ctrl-click 与 context action |
| Diagnostics | unknown table/column、parser error、execution error | 视口级异步诊断 |
| INSERT 值提示 | VALUES 中显示对应列名 |
inline widget/decorations |
SELECT * 展开 |
结合 source 与 metadata 安全展开 | completion/intention action |
| 参数 | 多种 placeholder、类型输入、preview | execution preprocessing pipeline |
| SQL 变量 | @set 声明和引用展开 |
参数处理前执行 |
| Format/Compress | 方言格式化与压缩 | selection/full document action |
| Snippet | 内置、自定义、方言改写 | completion source |
IN 粘贴 |
列表转 SQL literals | editor action |
| 状态持久化 | selection、viewport、tab 生命周期 | tab state snapshot |
| 结果联动 | statement 状态、summary、source focus | execution fingerprint + source map |
4. 统一数据契约
本节是 Phase 0 必须先确定的 contract。后续实现不得绕过这些结构自行传裸字符串和裸 offset。
4.1 Offset 约定
内部 SQL 分析统一使用 UTF-8 byte offset:
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct SqlTextRange {
/// Inclusive UTF-8 byte offset.
pub start_byte: usize,
/// Exclusive UTF-8 byte offset.
pub end_byte: usize,
}
约束:
start_byte <= end_byte <= text.len();- 两端都必须位于 UTF-8 char boundary;
end_byteexclusive;- UI Rope offset、GPUI text offset、LSP UTF-16 position 只在边界层转换;
- 禁止在同一结构中混用 byte、char 和 UTF-16 offset;
- debug build 中应对 range 做 boundary assertion。
建议新增显式转换 API:
fn sql_byte_to_rope_offset(text: &Rope, byte: usize) -> Result<usize>;
fn rope_offset_to_sql_byte(text: &Rope, offset: usize) -> Result<usize>;
fn sql_byte_to_line_column(text: &str, byte: usize) -> SqlLineColumn;
fn lsp_position_to_sql_byte(text: &str, position: LspPosition) -> Result<usize>;
4.2 Document snapshot
#[derive(Clone)]
pub struct SqlDocumentSnapshot {
pub revision: u64,
pub text: Arc<str>,
pub database_type: DatabaseType,
pub scope: SqlMetadataScope,
}
Revision 规则:
- 每次文档内容变化递增;
- 不因 selection、viewport 或主题变化递增;
- connection/database/schema/dialect 变化即使文本未变,也必须使 analysis/completion 请求失效;
- revision 不要求跨应用启动持久化,只需当前 editor instance 内单调递增。
4.3 Connection/metadata scope
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SqlMetadataScope {
pub connection_id: ConnectionId,
pub catalog: Option<Arc<str>>,
pub database: Option<Arc<str>>,
pub schema: Option<Arc<str>>,
pub database_type: DatabaseType,
pub generation: u64,
}
generation 在以下情况递增:
- connection 切换;
- database/catalog/schema 切换;
- session context 变化;
- DDL 执行后 metadata invalidation;
- 用户主动刷新 metadata;
- driver completion context version 变化。
4.4 Qualified identifier
#[derive(Clone, Debug)]
pub struct QualifiedIdentifier {
pub parts: Vec<IdentifierPart>,
pub range: SqlTextRange,
}
#[derive(Clone, Debug)]
pub struct IdentifierPart {
/// SQL 中的原始文本,不含或包含 quote 的策略必须全局一致。
pub raw: Arc<str>,
/// 按当前 dialect 规则归一化后的查找值。
pub normalized: Arc<str>,
pub quoted: bool,
pub quote_style: Option<SqlIdentifierQuoteStyle>,
pub range: SqlTextRange,
}
必须保留:
"Foo";`Foo`;[Foo];- 未加引号的
foo。
不能在 tokenizer 后无条件 lowercase,因为 quoted identifier 的大小写语义可能不同。
4.5 Analysis snapshot
#[derive(Clone)]
pub struct SqlAnalysisSnapshot {
pub document_revision: u64,
pub scope_generation: u64,
pub statements: Arc<[SqlStatementRange]>,
pub tokens: Arc<[SqlToken]>,
pub semantic_model: Arc<SqlSemanticModel>,
pub diagnostics: Arc<[SqlDiagnostic]>,
}
Snapshot 是只读、可共享、带版本的。UI 和后台任务不可原地修改旧 snapshot。
5. Statement Range Engine
5.1 DBX 事实
DBX 的 SqlTextRange 结构包含:
type SqlTextRange = {
from: number
to: number
sql: string
}
其中:
to是 exclusive;- 正常 range 不包含 statement 末尾分号;
- 正常 range 不包含语句间空白;
- 内部
RawStatement额外包含hitFrom; hitFrom表示光标位于前置缩进/空白时,仍可归属该 statement 的起点;from仍是实际 SQL 内容的第一个字符。
证据:
dbx/apps/desktop/src/lib/sql/sqlStatementRanges.ts:7-15dbx/apps/desktop/src/lib/sql/sqlStatementRanges.ts:42-51dbx/apps/desktop/src/lib/sql/sqlStatementRanges.ts:282-358
5.2 Navop 目标模型
#[derive(Clone, Debug)]
pub struct SqlStatementRange {
/// 光标归属范围的起点,可包含前置空白。
pub hit_start_byte: usize,
/// 实际 executable SQL,不含分隔符和 statement 间空白。
pub sql_range: SqlTextRange,
/// 可选分隔符范围,例如 `;`、GO 行、Oracle `/`。
pub delimiter_range: Option<SqlTextRange>,
/// gutter marker 所在 logical source row。
pub executable_line: usize,
pub kind: SqlStatementKind,
pub batch_index: usize,
}
pub enum SqlStatementKind {
Sql,
Procedure,
Function,
Trigger,
AnonymousBlock,
MongoCommand,
RedisCommand,
ElasticsearchRequest,
Directive,
}
5.3 必须支持的 lexical state
Scanner 至少需要维护:
enum SqlLexicalState {
Normal,
SingleQuotedString,
DoubleQuotedIdentifierOrString,
BacktickIdentifier,
BracketIdentifier,
LineCommentDash,
LineCommentHash,
BlockComment { depth: usize },
DollarQuotedString { tag: Arc<str> },
}
注意:
- PostgreSQL 支持 dollar quote;
- 某些数据库支持嵌套块注释,能力应由 dialect profile 控制;
- MySQL
#可能是 comment,但 MyBatis#{name}不是; - MySQL 中
--是否为注释需要遵守其空白规则; - SQL Server 方括号 identifier 内的
;、GO不得切分; - string/comment 内的 delimiter 永远不能切 statement。
5.4 必须支持的 delimiter/batch
DBX 已处理:
- 顶层
;; - MySQL
DELIMITER; - SQL Server
GO/GO n; - Oracle 行首单独
/; - Oracle PL/SQL block;
- MySQL procedure/function/trigger routine block;
- Mongo、Redis、Elasticsearch 的特殊 command range。
主要证据:
sqlStatementRanges.ts:292-558sqlStatementRanges.ts:689-710sqlStatementRanges.ts:1510-1564sqlStatementRanges.ts:1778-1845sqlStatementRanges.ts:1969-2001sqlStatementRanges.ts:2075-2085
5.5 Current statement 归属规则
statement_at_cursor(offset) 必须满足:
- offset 先 clamp 到
[0, text.len()]; - cursor 位于 statement SQL 内容内部时返回该 statement;
- cursor 位于 statement 前的缩进空白,可归属后一个 statement;
- cursor 位于 statement 后的同一行空白或 delimiter gap,可归属前一 statement;
- cursor 位于纯空白行或纯注释行时返回
None; - 前导普通注释不能被误认为 executable statement;
- executable directive 可将运行图标定位到 directive 后真正 SQL 起始行;
- 返回的 executable range 仍从实际 SQL 内容开始,不包含命中用空白。
DBX 证据:
sqlStatementRanges.ts:605-640executableStatementRangeCache.ts:89-130statementDelimiter.ts:8-70
5.6 Cache
建议:
pub struct SqlStatementRangeCache {
revision: u64,
database_type: DatabaseType,
parameter_syntax_key: u64,
ranges: Arc<[SqlStatementRange]>,
by_sql_start: HashMap<usize, usize>,
by_executable_line: HashMap<usize, usize>,
}
仅在以下变化时重建:
- document revision;
- database type/dialect;
- parameter syntax/profile;
- parser behavior version。
查询必须是 O(log n) 或 O(1):
statement_at_cursor(offset);statement_starting_on_line(row);statements_intersecting(range);statement_by_sql_start(byte)。
5.7 不应直接复用 StreamingSqlParser
Navop 当前 crates/db/src/streaming_parser.rs 面向大文件/大脚本流式执行,公开模型是 source、bytes read 和 progress,不是长期存活编辑器的 revision snapshot。
实现原则:
- 编辑器 range engine 放在新模块;
- 如两者要复用分隔逻辑,抽出无 UI、无 I/O 的纯 scanner;
StreamingSqlParser和 editor service 分别做 adapter;- 不让 UI 依赖流式 parser 的读取状态;
- 当前
streaming_parser.rs有既存未提交修改,本设计实现不得覆盖或回滚。
6. 左侧运行图标与通用 Gutter
6.1 DBX 用户行为
- 只有每条 executable statement 的起始行显示 play icon;
- 多行 statement 不在每一行重复显示;
- 前导空行和普通注释行不显示;
- MySQL routine 整体只显示一个运行入口;
- 只响应左键
mousedown; - 查不到 statement range 时不处理;
- gutter 点击始终执行对应 statement,即使全局执行模式设置为 All;
- 点击 gutter 不主动 focus editor,不把 viewport 滚回旧 cursor;
- marker 可显示 running、succeeded、failed;
- 文档变化时旧 marker 清空;
- execution state effect 到达时重新生成 marker。
证据:
dbx/apps/desktop/src/components/editor/QueryEditor.vue:1675-1687dbx/apps/desktop/src/components/editor/QueryEditor.vue:4704-4749
6.2 GPUI 通用 API
在 crates/ui/src/input/state.rs 新增通用模型:
#[derive(Clone)]
pub struct InputGutterMarker {
pub id: SharedString,
pub logical_row: usize,
pub lane: InputGutterLane,
pub icon: IconName,
pub state: InputGutterMarkerState,
pub tooltip: Option<SharedString>,
pub enabled: bool,
pub action: Option<InputGutterAction>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum InputGutterLane {
PrimaryAction,
Diagnostic,
Breakpoint,
Custom(u8),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum InputGutterMarkerState {
Idle,
Running,
Success,
Error,
Disabled,
}
建议 InputGutterAction 不直接持有 SQL closure,而使用稳定 id 发通用 event:
pub enum InputEvent {
// existing events...
GutterMarkerMouseDown {
marker_id: SharedString,
logical_row: usize,
button: MouseButton,
},
}
6.3 Layout 与 hit-testing
修改 crates/ui/src/input/element.rs:
- gutter 由固定 lane 组成:
- marker lane;
- fold lane;
- line number lane;
- gutter 总宽度取决于启用 lane,不应因某一行有无 marker 而抖动;
- marker 使用 logical source row,而不是 soft-wrap visual row;
- 一条 source line 被 soft wrap 后,只在第一个 visual fragment 显示;
- 横向滚动只影响文本,不移动 gutter;
- marker 每个实例有独立 hitbox;
- marker hitbox 优先于 line-number/fold/text hitbox;
mousedown命中后 stop propagation,避免改变 cursor/selection;- tooltip 使用通用 hover/popover 生命周期;
- fold 后不可见行的 marker 不绘制。
6.4 SQL facade
crates/db_view/src/sql_editor.rs 增加:
impl SqlEditor {
pub fn set_statement_gutter_markers(
&mut self,
markers: Vec<SqlStatementGutterMarker>,
cx: &mut Context<Self>,
);
}
pub struct SqlStatementGutterMarker {
pub statement_start_byte: usize,
pub logical_row: usize,
pub state: SqlExecutionMarkerState,
}
Marker id 推荐编码为:
sql-statement:{document_revision}:{start_byte}:{end_byte}
事件处理时不能只相信 marker 中的旧 SQL。必须:
- 解析 marker id;
- 确认当前 document revision 相同;
- 从当前 snapshot 重新按 start/end 查 range;
- 创建
ExactRangeexecution request。
7. 执行目标解析
7.1 DBX 优先级
DBX 的执行选择逻辑:
- 有非空 selection:执行 selection;
- 否则构造 current/all candidates;
- shortcut 路径 bypass picker;
- toolbar 点击在设置开启且存在多个候选时可显示 picker;
- gutter 永远执行精确 statement range。
DBX 的 ExecutionSnapshot 包含:
fullSqlselectedSqlcursorPosselectionFromselectionTo- 可选
editorViewportRequestId
证据:
QueryEditor.vue:822-885sqlExecutionTarget.ts:7-14sqlExecutionTarget.ts:45-78
7.2 Navop 目标模型
pub enum SqlExecutionTarget {
Selection(SqlTextRange),
CurrentStatement,
AllStatements,
ExactRange(SqlTextRange),
}
pub struct SqlExecutionRequest {
pub request_id: u64,
pub document_revision: u64,
pub full_sql: Arc<str>,
pub target: SqlExecutionTarget,
pub resolved_sql: Arc<str>,
pub source_range: Option<SqlTextRange>,
pub statement_identity: Option<SqlStatementIdentity>,
pub scope: SqlMetadataScope,
pub transaction_mode: TransactionMode,
pub open_in_new_result_tab: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SqlStatementIdentity {
pub document_revision: u64,
pub start_byte: usize,
pub end_byte: usize,
pub sql_fingerprint: u64,
}
7.3 入口行为
| 入口 | Target | 是否使用 picker | 是否改 selection/focus |
|---|---|---|---|
| Gutter play | ExactRange |
否 | 否 |
| Run shortcut | Selection 或 Current | 否 | 否 |
| Run All shortcut | AllStatements |
否 | 否 |
| Toolbar Run | Selection/Current/All | 可配置 | 否 |
| Context menu Run Selection | Selection |
否 | 右键前同步 selection |
| Context menu Run Current | CurrentStatement |
否 | 右键前同步 pointer target |
7.4 执行前处理顺序
推荐统一 pipeline:
resolve target from snapshot
→ extract source SQL
→ expand declared SQL variables
→ extract unresolved parameters
→ optional parameter dialog
→ substitute parameters
→ construct dialect-specific batch script
→ execute
→ bind result to statement identity
变量展开必须先于 placeholder 参数替换。未声明变量应保留给参数系统。
7.5 执行状态
pub enum SqlExecutionState {
Pending,
Running,
Succeeded,
Failed,
Cancelled,
Skipped,
}
文档一旦编辑:
- 旧 marker 不能继续附着到新文本;
- 可以保留历史 result tab;
- 但 result tab 的 source highlight 必须标明它属于旧 revision;
- 若 fingerprint 无法匹配当前 statement,不得自动跳转到错误 range。
8. SQL 分析层
8.1 推荐模块
crates/db/src/sql_editor/
├── document.rs
├── dialect.rs
├── identifier.rs
├── statement_ranges.rs
├── analysis.rs
├── semantic_model.rs
├── diagnostics.rs
├── completion.rs
└── metadata.rs
如需降低首期改动,至少先新增:
statement_ranges.rs
identifier.rs
analysis.rs
metadata.rs
8.2 Tokenizer
Navop 当前 tokenizer 已支持:
- keyword;
- ident/quoted ident;
- string;
- number;
- line/block comment;
- dot/comma/semicolon/parenthesis/operator;
- byte spans;
- token at offset。
现有文件:
navop/crates/db/src/sql_editor/sql_tokenizer.rs
需要扩展:
- database dialect profile;
- backtick 和 bracket identifier;
- PostgreSQL dollar quote;
- incomplete string/comment 的稳定 token;
- parameter token;
- executable directive;
- token 中保留 raw text 与 normalized identifier;
- error/recovery token;
- statement scanner 可复用的 lexical state。
8.3 Semantic model
最低目标:
pub struct SqlSemanticModel {
pub statements: Vec<SqlSemanticStatement>,
pub references: Vec<SqlReference>,
pub scopes: Vec<SqlScope>,
}
pub struct SqlScope {
pub parent: Option<SqlScopeId>,
pub row_sources: Vec<SqlRowSource>,
pub projection_columns: Vec<SqlDerivedColumn>,
pub ctes: Vec<SqlCte>,
}
pub enum SqlRowSource {
Table(SqlTableReference),
Cte(SqlCteReference),
DerivedTable(SqlDerivedTable),
TableFunction(SqlRoutineReference),
}
必须解析或保守推导:
FROM table [AS] alias;JOIN table alias;- qualified table;
- CTE 名称和输出列;
- subquery/derived table alias 和 projection;
SELECT expr AS alias;- INSERT target;
- UPDATE target;
- function call;
- visible scope 与 correlated parent scope。
语义模型面对不完整 SQL 时应“尽可能返回已知信息”,而不是因为 parse error 整体失败。
8.4 Statement window
DBX 在有 live CodeMirror state 时优先使用增量 syntax tree;tree 尚未 parse 到 cursor、出现 recovery error 或 dollar quote 可能截断时,回退 bounded scanner。
Navop 不一定复制 CodeMirror tree,但应保留相同策略:
- 优先使用当前 revision 的 analysis snapshot;
- snapshot 未完成或 cursor 不在已分析范围时,使用轻量 bounded scanner;
- bounded scanner 默认向两侧最多扩展 32 KiB;
- 超长 statement 可按需要扩大窗口;
- 不在 UI thread 强制等待完整解析。
9. 自动完成
9.1 DBX 分层
DBX completion 的概念流程:
cursor lexer/parser
→ CompletionContext
→ local semantic candidates
→ metadata tree/cache candidates
→ remote completion assistant
→ merge/filter/rank/dedupe
→ editor CompletionResult
这意味着“字段完成提示”不是简单地把所有列名放进一个数组。
9.2 Completion context
目标 context:
pub enum SqlCompletionContextKind {
Start,
Keyword,
Catalog,
Schema,
Table,
Routine,
Column,
AliasColumn,
InsertTarget,
InsertColumn,
UpdateTarget,
SetClause,
Condition,
JoinSource,
JoinCondition,
OrderBy,
GroupBy,
FunctionArgument,
ExecArgument,
}
Request:
pub struct SqlCompletionRequest {
pub request_id: u64,
pub document_revision: u64,
pub cursor_byte: usize,
pub trigger: SqlCompletionTrigger,
pub scope: SqlMetadataScope,
pub replacement_range: SqlTextRange,
pub context: SqlCompletionContext,
pub analysis: Arc<SqlAnalysisSnapshot>,
}
9.3 Candidate 数据
pub struct SqlCompletionCandidate {
pub label: Arc<str>,
pub insert_text: Arc<str>,
pub replacement_range: SqlTextRange,
pub kind: SqlCompletionItemKind,
pub detail: Option<Arc<str>>,
pub documentation: Option<Arc<str>>,
pub filter_text: Option<Arc<str>>,
pub sort_text: Option<Arc<str>>,
pub source: SqlCompletionSourceKind,
pub score: i32,
pub deprecated: bool,
pub snippet: bool,
pub commit_characters: Arc<[char]>,
}
pub enum SqlCompletionItemKind {
Catalog,
Database,
Schema,
Table,
View,
MaterializedView,
Column,
Alias,
Function,
Procedure,
Package,
Trigger,
Sequence,
Keyword,
Snippet,
Value,
}
字段 candidate 至少保存:
- column name;
- physical table;
- source alias;
- source qualifier SQL;
- schema;
- data type;
- nullable;
- comment。
表 candidate 至少保存:
- catalog/database/schema;
- object type;
- detail/comment;
- apply name;
- boost。
Routine candidate 至少保存:
- parent schema/name;
- signature;
- comment;
- overload identity。
9.4 Completion source
pub trait SqlCompletionSource: Send + Sync {
fn complete(
&self,
request: SqlCompletionRequest,
cx: &mut AsyncApp,
) -> Task<Result<SqlCompletionSourceResult>>;
}
pub struct SqlCompletionSourceResult {
pub request_id: u64,
pub document_revision: u64,
pub scope_generation: u64,
pub candidates: Vec<SqlCompletionCandidate>,
pub incomplete: bool,
}
建议 source:
DialectKeywordCompletionSourceSemanticCompletionSourceMetadataCompletionSourceRoutineCompletionSourceSnippetCompletionSourceHistoryCompletionBoostSource
由 MergedSqlCompletionProvider 合并。不要让 schema refresh 直接替换整个 provider。
9.5 表和 schema 补全
必须支持:
table;schema.table;- MySQL 风格
database.table; database.schema.table;- quoted schema 后的 dot completion;
- catalog/database/schema 切换;
- table/view/materialized view 类型区分;
- INSERT/UPDATE target;
- JOIN source;
- 自动 alias,可配置;
- Oracle 等不支持 table alias
AS的方言差异。
生成 alias 时:
- 多词表名可使用首字母;
- alias 冲突时加编号;
- 不覆盖显式 alias;
- 设置关闭时不生成;
- quoted table 需要按方言生成合法 alias。
9.6 字段完成提示
字段 completion 的解析顺序:
- 从当前 statement semantic scope 收集 row source;
- 分辨 physical table、CTE、derived table 和 table function;
- 对
alias.只返回该 source 的 columns; - 对未限定字段,根据所有 visible row source 合并;
- 同名列需要显示来源并降低歧义;
- CTE/subquery 的投影列不需要远端 metadata;
- physical table cache miss 时异步请求 columns;
- remote 返回前可显示已有 local candidates;
- remote 返回后仅在 request/revision/scope 仍有效时刷新 popup。
必须覆盖:
SELECT | FROM users u→ users fields;SELECT u.| FROM users u→ onlyufields;JOIN orders o ON u.id = o.|→ orders fields;- correlated subquery 可看到合法 parent scope;
UPDATE users SET |→ target table fields;INSERT INTO users (|)→ target table fields;ORDER BY |可包含 projection alias;- projection alias 在 WHERE/GROUP BY/HAVING/ORDER BY 的可见性按 dialect 控制;
- 不完整 metadata 时不应错误展开
*或报 unknown column。
9.7 SELECT * 展开
DBX 支持结合 semantic source 和 metadata 展开 wildcard。
Navop 行为:
-
单表:
SELECT * FROM users;展开为列列表。
-
alias:
SELECT u.* FROM users u;展开时保留
u.qualifier。 -
多表:
- 保持 FROM/JOIN source 顺序;
- 同名列根据设置使用 qualifier;
- metadata 不完整或 stale 时拒绝操作,不生成猜测结果;
- 异步返回后确认旧 SQL 与当前 document revision/range 内容一致。
9.8 Function/routine 与 signature help
Completion:
- function name;
- signature;
- return type;
- schema/package;
- overload;
- snippet-style parameters;
- 已有
(时不重复插入。
Signature help:
- cursor 位于 argument list 时显示;
- 标出 active parameter;
- overloaded routine 可切换;
- 文档编辑或 cursor 离开 call 时关闭;
- metadata scope 变化使旧 signature 失效。
9.9 Snippet
DBX 内置 prefix 包括:
selinsupdctejoincasectexnexatci
并有 Manticore 专用模板。
Navop 应支持:
- 内置 snippet;
- 用户自定义 snippet;
- tab stop;
- next/previous field;
- dialect-specific body;
- 只有用户仍使用内置默认 body 时才自动做 dialect 改写;
- 用户自定义 body 永不被 silently rewrite。
典型方言改写:
LIMITTOPFIRSTFETCH FIRSTROWSROWNUM- ClickHouse
ALTER TABLE ... UPDATE - 不同
ALTER TABLE ADD COLUMN形式。
9.10 排序、过滤和去重
DBX 排序综合:
- context/variable/exact;
- fuzzy score;
- history boost;
- type boost。
DBX type boost 示例:
- column: 180
- table: 160
- schema: 120
- function: 90
- keyword: 0
Navop 推荐评分:
final_score =
exact_prefix_score
+ context_score
+ semantic_visibility_score
+ item_kind_score
+ history_score
+ fuzzy_score
- qualification_penalty
- ambiguity_penalty
匹配至少支持:
- exact;
- case-insensitive prefix;
- identifier initials;
- substring;
- ordered fuzzy subsequence;
- 可选汉字拼音首字母。
去重 key 不能只用 label,应包含:
kind + qualified identity + insert_text + signature
9.11 Completion stale 防护
必须有单调递增 completion_epoch 或 request id。
以下事件使旧请求失效:
- document changed;
- cursor/selection 变化导致 context 改变;
- popup abort;
- connection/catalog/database/schema 变化;
- dialect/profile 变化;
- metadata generation 变化;
- IME composition start;
- editor deactivation;
- completion setting/snippet setting 变化。
每个关键 await 后都要检查:
if !completion_guard.is_current(
request_id,
document_revision,
scope_generation,
) {
return Ok(None);
}
10. Metadata Model 与 Cache
10.1 Navop 当前问题
当前 SqlSchema 主要包含:
- tables;
- global columns;
- functions;
- columns_by_table。
缺少:
- catalog/database/schema;
- object kind;
- table/view distinction;
- PK/FK/index;
- nullable/default/comment;
- routine overload;
- qualification/quoted state;
- revision/version。
当前 schema 加载还存在逐表串行请求 columns 的 N+1 风险。
10.2 Metadata contract
pub trait SqlMetadataProvider: Send + Sync {
fn search_objects(
&self,
request: SearchSqlObjectsRequest,
cx: &mut AsyncApp,
) -> Task<Result<SearchSqlObjectsResponse>>;
fn list_columns(
&self,
request: ListSqlColumnsRequest,
cx: &mut AsyncApp,
) -> Task<Result<ListSqlColumnsResponse>>;
fn get_object_detail(
&self,
request: GetSqlObjectDetailRequest,
cx: &mut AsyncApp,
) -> Task<Result<SqlObjectDetail>>;
fn get_ddl(
&self,
request: GetSqlObjectDdlRequest,
cx: &mut AsyncApp,
) -> Task<Result<SqlObjectDdl>>;
}
10.3 Object model
pub enum SqlObjectKind {
Catalog,
Database,
Schema,
Table,
View,
MaterializedView,
Function,
Procedure,
Package,
Trigger,
Sequence,
}
pub struct SqlObjectRef {
pub kind: SqlObjectKind,
pub catalog: Option<Arc<str>>,
pub database: Option<Arc<str>>,
pub schema: Option<Arc<str>>,
pub name: Arc<str>,
pub quoted_parts: Arc<[bool]>,
}
pub struct SqlColumnMetadata {
pub name: Arc<str>,
pub data_type: Arc<str>,
pub nullable: Option<bool>,
pub default_value: Option<Arc<str>>,
pub comment: Option<Arc<str>>,
pub ordinal: Option<u32>,
pub primary_key: bool,
pub generated: bool,
}
pub struct SqlObjectDetail {
pub object: SqlObjectRef,
pub comment: Option<Arc<str>>,
pub columns: Arc<[SqlColumnMetadata]>,
pub primary_key: Arc<[Arc<str>]>,
pub indexes: Arc<[SqlIndexMetadata]>,
pub foreign_keys: Arc<[SqlForeignKeyMetadata]>,
pub signature: Option<Arc<str>>,
}
10.4 Search assistant contract
DBX remote assistant 请求包括:
- connection id;
- database;
- schema;
- object kinds;
- mask;
- case sensitivity;
- global search;
- max results;
- search comments/definitions;
- parent schema/name;
- match mode。
Response 包括:
- candidates;
- incomplete;
- fallback used。
Navop 应保留等价字段,以便:
- completion;
- object search;
- navigation;
- hover cache miss;
- large schema lazy lookup。
10.5 Cache key
至少包含:
pub struct SqlMetadataCacheKey {
pub connection_id: ConnectionId,
pub catalog: Option<Arc<str>>,
pub database: Option<Arc<str>>,
pub schema: Option<Arc<str>>,
pub object: Option<Arc<str>>,
pub object_kind: Option<SqlObjectKind>,
pub quoted_parts: Arc<[bool]>,
pub database_type: DatabaseType,
pub session_context: Option<Arc<str>>,
}
禁止仅按裸 table_name 缓存 columns。
10.6 Cache 写入规则
请求发起时捕获:
- connection generation;
- database generation;
- scope generation。
返回后:
if current_scope.generation != requested_generation {
// Discard. Do not write into cache.
return;
}
建议分层 cache:
- object search:短 TTL;
- columns:中 TTL;
- object detail:中 TTL;
- DDL:中/长 TTL,但 DDL 后立即 invalidation;
- negative result:很短 TTL;
- session-scoped metadata:绑定 session id/version。
10.7 大 schema 策略
禁止连接后串行加载全部表的全部字段。
推荐:
- 初始只加载 catalog/database/schema/table/view 基础索引;
- 当前 statement 引用的表优先加载 columns;
alias.或 INSERT target 触发按表加载;- hover 触发 detail/DDL lazy load;
- 使用 bounded concurrency;
- 支持分页和
incomplete; - cache entry 记录 memory cost;
- LRU 驱逐;
- completion popup 本地响应预算内先返回,再增量补远端。
11. Hover、对象详情与导航
11.1 Identifier 定位
DBX 行为:
- cursor 可位于 token 内,也可刚好位于 token 后;
- 未加引号的 SQL keyword 不作为对象;
- 支持一至三/四段 qualified identifier;
- database/schema/table 含义按 dialect 解释;
- metadata 查找可 case-insensitive,但 quoted state 必须保留;
- local lookup 必须校验 connection/database/schema/object。
主要证据:
queryCursorTableTarget.ts:32-108queryCursorTableTarget.ts:155-181
11.2 Hover resolve pipeline
pointer position
→ GPUI offset
→ SQL byte offset
→ token/qualified identifier
→ reject string/comment/keyword
→ semantic reference resolution
→ local metadata cache
→ optional remote detail/DDL
→ revision + scope validation
→ render popover
失败行为:
- 找不到对象:静默不显示;
- metadata 请求失败:hover 内可显示轻量错误或静默关闭;
- 不弹全局 error toast;
- 旧请求返回:丢弃;
- pointer 已离开目标:不显示。
11.3 支持对象类型
至少:
- table;
- view;
- materialized view;
- procedure;
- function;
- package;
- trigger。
建议扩展:
- sequence;
- schema;
- database;
- column。
11.4 Table hover 内容
详情应包括:
- object type;
- catalog/database/schema;
- comment;
- columns;
- type length/precision/scale;
- nullable;
- default;
- generated/extra;
- column comment;
- primary key;
- indexes;
- foreign keys;
- backend DDL;
- companion
COMMENT ON/CREATE INDEX。
11.5 DDL 权威性
规则:
- driver/backend
get_ddl是权威来源; - sanitize 只能清理展示噪声;
- parse/reformat 不安全时展示 sanitized raw DDL;
- 不得因为 formatter 失败而丢掉结构;
- metadata 构造的
CREATE TABLE只作 fallback; - fallback 必须标注“根据元数据生成的预览,不保证可执行”;
- fallback 不得进入“复制并执行”默认路径。
DBX 证据:
hoverTableSql.ts:5-117hoverTableSql.ts:290-354hoverTableSql.ts:753-825
11.6 Hover layout
参考 DBX:
- max width 900px;
- width 80vw;
- max height 约半个 viewport;
- content max height 480px;
- vertical scroll;
- 超宽 SQL 支持 horizontal scroll;
- wheel 和 Shift+wheel;
- resize 时重新布局;
- destroy 时清理 controller/listener。
GPUI 版本不必逐像素一致,但必须:
- 不遮满整个编辑器;
- DDL 可横向滚动;
- 长 column list 可纵向滚动;
- popover 可复制;
- pointer 离开、editor destroy、tab deactivation 时清理异步任务与 listener。
11.7 Navigation
交互:
- Cmd/Ctrl + click;
- context menu;
- hover 中 action;
- completion resolve action。
目标:
- 打开对象结构;
- 打开数据;
- 查看 DDL/source;
- 跳到已打开对象 tab。
Table actions:
- View Data
- Edit Structure
- View DDL
View/materialized view actions:
- View Data
- Edit View
- View Source
- View DDL
右键菜单必须使用本次 pointer 坐标同步出的 target,不能复用旧 hover/cursor target。
12. Diagnostics
12.1 DBX 当前范围
DBX 核心 diagnostics 包括:
- unknown table;
- unknown column;
- parser error;
- database execution error 的 line/column 映射。
它不是完整 SQL lint 规则集。
12.2 Contract
pub struct SqlDiagnostic {
pub id: u64,
pub document_revision: u64,
pub range: SqlTextRange,
pub severity: SqlDiagnosticSeverity,
pub code: Option<Arc<str>>,
pub message: Arc<str>,
pub source: SqlDiagnosticSource,
pub related: Arc<[SqlDiagnosticRelatedInfo]>,
}
pub enum SqlDiagnosticSeverity {
Error,
Warning,
Information,
Hint,
}
pub enum SqlDiagnosticSource {
Parser,
Semantic,
Metadata,
Execution,
}
12.3 诊断逻辑
Parser:
- unclosed string/comment;
- invalid token;
- parser recovery error;
- line/column/span。
Semantic:
- unknown table;
- unknown column;
- unknown alias;
- ambiguous column 可作为 warning;
- metadata 不完整时避免误报;
- 多表同名字段不能直接报 unknown;
- CTE、subquery、correlated scope 正确处理。
Execution:
- 只有 result 对应的 SQL fingerprint/revision 与当前文档相符时显示;
- driver line/column 转为 source range;
- execution target 是 selection/exact range 时加上 source base offset;
- 无法可靠映射时只在 result panel 显示,不在错误位置画波浪线。
12.4 Viewport 分析
DBX 按可见 viewport 相交的完整 statements 分析。
Navop 策略:
- 从
visible_row_range()转为 byte range; - 用 statement snapshot 扩展到完整 statement;
- 同一 statement 只分析一次;
- cursor 所在超长 statement 即使只可见中段也必须完整分析或采用 safe window;
- 视口外旧 diagnostics 可暂时保留;
- 更新时只替换受影响 statement ranges;
- Oracle PL/SQL、procedure/function batch 可先跳过 semantic unknown-column 规则;
- Mongo/Elasticsearch 等非 SQL language mode 跳过 SQL diagnostics。
12.5 Debounce 与 stale
使用独立 diagnostic_run_id,不得复用 completion request id。
- 文档变化:递增、清当前 stale decoration、重新调度;
- 默认 debounce 500ms;
- completion active 或用户处于 table-name 输入状态时可延长;
- 每个 metadata await 后检查 run id/revision/generation;
- tab deactivate 取消 timer 并使 run id 失效;
- activate 后重新调度可见范围。
13. 当前 Statement Frame 与 Decorations
DBX 在以下条件显示当前 statement 边框:
- setting 开启;
- selection 为空;
- cursor 可解析到 executable statement。
规则:
- executable range 本身可以不含
;; - frame 可把紧邻 trailing
;纳入; - 注释、空行或非 delimiter 字符会阻断 frame 延伸;
- selection 非空时 frame 隐藏,避免和 selection 视觉冲突。
Navop 可在 Input 增加:
pub struct InputRangeDecoration {
pub id: SharedString,
pub range: Range<usize>,
pub kind: InputRangeDecorationKind,
pub style: InputRangeDecorationStyle,
}
建议绘制顺序:
line background
→ current statement frame
→ selection/search match
→ syntax text
→ semantic underline
→ diagnostics squiggle
→ hover highlight
→ caret
→ inline widget
14. INSERT 值列名提示
14.1 用户行为
在:
INSERT INTO users (name, age)
VALUES ('Alice', 18),
('Bob', 20);
每个 value expression 前显示不可编辑的灰色提示:
name: 'Alice', age: 18
14.2 解析
需要识别:
- target table;
- database/schema/table;
- explicit column list;
- 每一行
VALUES (...); - 每行顶层 expression 起点;
INSERT ... SELECTprojection;- 无 explicit columns 时从 metadata 按 ordinal 获取表字段。
14.3 性能
参考 DBX:
- 只分析 viewport 与主 cursor 附近;
- 单侧默认最多扩展 32 KiB;
- doc/viewport 变化后约 80ms debounce;
- 重解析前 widget range 随 edit mapping;
- 同一 offset 去重;
- metadata cache miss 时先触发异步加载,不显示错误列名。
14.4 GPUI 表达
可以复用现有 inline completion 的布局基础,但必须区分:
- inline completion 是可接受的 ghost text;
- INSERT value hint 是不可接受、不可编辑的 decoration widget。
建议新增 InputInlineWidget 通用模型,或在 range decoration 中增加 before_text,但不要伪装为真实文档文本。
15. 编辑辅助
15.1 单引号 caret
行为:
- 光标在自动生成的
''中按':跳过右侧 closing quote; - 已有 opening quote 且缺少 closing quote:插入 SQL escaped quote;
- 普通位置交给默认输入;
- read-only、多 selection、非空 selection 时不拦截;
- auto-close 关闭时不拦截。
15.2 IN (...) 列表粘贴
输入来源:
- 当前 selection;
- clipboard。
支持:
- comma;
- tab;
- newline;
- 已有
IN (...); - 简单 slash 列表;
NULL;- 单引号 escape。
保护:
- 最大 1 MiB;
- 最多 10,000 values;
- 单个普通文本拒绝;
- 日期、URL、绝对路径不能误判为 slash list;
- cursor 已在
IN/NOT IN后时只插括号内容。
15.3 Selection case conversion
提供:
- Uppercase;
- Lowercase。
要求:
- 只处理非空 selection;
- 保持转换后的 range 选中;
- string literal 保持原文;
- PostgreSQL dollar quote 保持;
- dialect-specific quoted string/identifier/executable comment 保护;
- 不做简单的整个字符串
to_uppercase()。
15.4 SQL 参数
支持 descriptor:
pub enum SqlParameterSyntax {
Positional,
Named,
Shell,
MyBatis,
SqlServer,
}
pub enum SqlParameterValueKind {
String,
Number,
Boolean,
Null,
Raw,
}
执行前:
- extract descriptors;
- 去重但保留 occurrence;
- 显示参数 dialog;
- 类型和值输入;
- 替换后 SQL preview;
- execute。
Literal:
- null →
NULL; - raw → 原样;
- number → 不加 quote;
- string → dialect-aware quote/escape;
- placeholder 在 string 内时使用 string fragment escape,不重复包裹。
MyBatis foreach:
- item/index;
- open/separator/close;
- collection 展开;
- enabled syntaxes 限制识别范围。
15.5 @set SQL 变量
支持:
@set ids = (1, 2, 3);
SELECT * FROM users WHERE id IN ${ids};
规则:
- 声明 key case-insensitive;
- value 保留原始 SQL;
- 不在 string/comment/quoted identifier 内替换;
@@version等原生变量不误替换;- declaration context 可来自 full document;
- 只删除本次 execution target 内的 declaration;
- 未声明 placeholder 留给参数系统;
- 变量展开先于参数 dialog。
15.6 Comment、line edit 与 folding
必须保留或新增:
- toggle line comment;
- toggle block comment;
- duplicate line;
- delete line;
- move line;
- indent/outdent;
- delete blank lines;
- fold/unfold;
- nested
BEGIN...END; - CASE;
- CTE/subquery;
- UNION;
- string/comment 中的关键字不参与 folding。
15.7 Drag/drop table 与 column
建议支持:
- schema tree 中 table 拖入 editor;
- column 拖入 editor;
- payload 带 source connection/database/schema/database type;
- context 不完整时拒绝;
- 按源 dialect quote identifier;
- 不依赖系统
dataTransfer再反查已失效对象; - multi-line selection/drop 位置正确。
16. 格式化与压缩
16.1 能力
- format selection;
- format full document;
- compress selection/document;
- SQL;
- Mongo;
- Elasticsearch;
- JSON;
- XML。
16.2 安全行为
- 输入上限建议 1,000,000 chars;
- XML-looking 内容不送 SQL formatter;
- editing surface 遇到 parse error 返回原文并提示;
- display surface formatter 失败返回 sanitized raw text;
- async format 返回时确认 document revision 和原 range 内容未变化;
- formatter 不得覆盖用户在等待期间的新编辑。
16.3 配置
- keyword case;
- type case;
- function case;
- identifier case;
- indentation;
- tab width;
- logical operator newline;
- FROM layout;
- expression width;
- query spacing;
- dense operators;
- semicolon;
- parameter style;
- JSON import/export。
16.4 Compress
必须保护:
- string 内空白;
- quoted identifier;
- MySQL executable/versioned/optimizer comments;
- PostgreSQL dollar quote;
- nested block comments;
- SQL Server bracket identifier;
- 未闭合 block comment 原文。
17. 快捷键、Toolbar 与 Context Menu
17.1 快捷键行为
至少:
- execute;
- execute in new result tab;
- execute all;
- save;
- format;
- compress;
SELECT *expansion;- find/replace;
- indent/outdent;
- duplicate/delete/move line;
- undo/redo;
- uppercase/lowercase;
- line/block comment;
- fold;
INpaste;- completion;
- signature help;
- next/previous snippet field。
DBX 的关键约束:
- Enter 不是执行,而是插入保持缩进的新行;
- Enter 先关闭 completion,并短暂抑制自动 completion;
- Tab 只有在 selection 为空时才允许 completion/snippet 接管;
- shortcut execution bypass picker;
- Vim 模式时 Vim keymap 优先。
17.2 Toolbar
DBX toolbar 能力包括:
- execute/cancel;
- Explain/cancel Explain;
- Explain Analyze/Autotrace;
- Format;
- Compress;
- keyword case;
- semantic diagnostics toggle;
- dangerous command toggle;
- save/open;
- import result archive;
INpaste;- multi-database execute;
- auto/manual transaction;
- commit/rollback。
Navop 可按现有产品范围分期,但 action contract 应预留:
pub enum SqlEditorAction {
Execute,
ExecuteAll,
ExecuteNewResult,
Cancel,
Explain,
ExplainAnalyze,
Format,
Compress,
ExpandWildcard,
PasteAsInList,
ToggleDiagnostics,
Commit,
Rollback,
}
17.3 Context menu 同步顺序
严格顺序:
- pointer coordinate → text offset;
- 根据 pointer 同步 selection;
- 同步 executable statement range;
- 同步 object target;
- 关闭旧 hover;
- 构建并打开 menu。
不能先打开菜单,再异步更新 target。
菜单建议:
- execute selection/current;
- execute in new result tab;
- object actions;
- expand
SELECT *; - comments;
- format/compress;
- copy/cut/paste;
- uppercase/lowercase;
- paste as SQL IN;
- find/replace;
- delete blank lines;
- select all。
18. 结果面板与编辑器联动
18.1 DBX 能力
- editor/result split pane;
- multiple result runs;
- result/summary/chart/messages;
- running/error/cancel/evicted/empty states;
- statement summary;
- statement status;
- 点击 statement 预览;
- 双击 statement 聚焦 source;
- execution end 后可滚动到 cursor statement;
- statement marker 与 result fingerprint 对齐。
18.2 Navop source map
pub struct SqlExecutionResultSource {
pub request_id: u64,
pub document_revision: u64,
pub source_range: Option<SqlTextRange>,
pub sql_fingerprint: u64,
pub statement_index: Option<usize>,
}
行为:
- result row/run 保留 source identity;
- 单击 result statement:编辑器 preview range;
- 双击:如果 current document revision 相同,scroll and select/focus;
- revision 不同但 fingerprint 唯一匹配时可提示用户跳转;
- 无法匹配时只展示 SQL snapshot,不在当前文档错误定位;
- 新 execution 不继承旧 execution 的 focused result index;
- message result 与 data result 的默认 focus 规则明确。
18.3 可编辑结果集
DBX 还有 SQL 分析支撑结果表 inline edit:
- 识别单表可编辑 SELECT;
- projection 到 source column 映射;
- primary key identity;
- join/quoted alias;
- set operation、DISTINCT、aggregation、computed column 等保守拒绝;
- 映射不唯一时只读,不猜测。
这部分可作为后续 phase,但 semantic model 设计不应阻断它。
19. 编辑器生命周期与状态
19.1 DBX 原则
DBX 使用:
单一长期存活的
EditorView+ Compartment 局部重配置
而不是 settings/props 每次变化时重建编辑器。
Navop 对应原则:
InputState/SqlEditorentity 长期存活;- theme、wrap、read-only、completion、diagnostics 开关通过状态更新;
- 不因 connection/schema 刷新而重建文本 entity;
- 保留 undo history、selection、viewport、composition。
19.2 Update flow
文档变化:
- increment revision;
- invalidate completion;
- invalidate diagnostics;
- clear current execution marker projection;
- schedule statement/semantic analysis;
- emit model change;
- persist selection/viewport(debounced)。
Selection/cursor 变化:
- update current statement frame;
- update signature help;
- update context action target;
- 不递增 document revision。
Viewport 变化:
- schedule viewport diagnostics;
- schedule INSERT hints;
- update visible semantic highlights;
- 不重算全文 metadata。
19.3 IME
Composition start:
- invalidate completion;
- 暂停会破坏 composition 的自动 edit;
- 不高频回写外部 model。
Composition end:
- flush final text;
- increment revision once or按实际 transaction;
- schedule diagnostics;
- schedule completion;
- 不接受 composition 前发出的 async result。
19.4 Deactivate/activate
Deactivate:
- flush selection/viewport;
- cancel hover pending;
- invalidate completion;
- cancel diagnostics timer;
- stop background UI refresh;
- unregister transient pointer/drop listeners;
- 不销毁 text state。
Activate:
- restore listeners;
- restore viewport/selection;
- schedule visible diagnostics;
- refresh metadata-dependent decorations;
- 按产品策略 restore focus。
Destroy:
- cancel timers/tasks/animation frames;
- remove window/pointer/scroll listeners;
- destroy popovers;
- release metadata subscriptions;
- clear marker hitboxes;
- 不让 callback 捕获已销毁 entity。
20. Navop 当前能力与差距
20.1 已有能力
crates/db_view/src/sql_editor.rs:
- SQL code editor;
- completion provider;
- hover provider 注入;
- actions;
- line number;
- soft wrap;
- schema/table/column/function 基础 completion;
- tokenizer + context inferrer + symbol table。
crates/db_view/src/sql_editor_view.rs:
- connection/database/schema;
- current/all/selected/cursor statement execution;
- transaction/session;
- result container;
- toolbar/editor/result 布局。
crates/ui/src/input/state.rs 与 element.rs:
- line number;
- line decoration background;
- diagnostics style;
- hover provider;
- completion menu;
- inline completion;
- visible row range;
- mouse point → offset;
- fold gutter;
- line number hitbox;
- range layout/paint。
20.2 主要差距
| 层 | 缺口 |
|---|---|
| Input | 通用 marker lane、marker icon/state/tooltip/action、独立 hitbox |
| Input | editor document revision 的公开 contract |
| Input | SQL diagnostics 可消费的公共 range model |
| Input | generic inline widget/decorations |
| SQL tokenizer | 完整方言 lexical state、dollar quote、delimiter/routine |
| Statement | editor-safe unified statement snapshot |
| Semantic | CTE、derived table、projection、reference graph |
| Completion | 多 source merge、stale request contract、qualified replacement |
| Metadata | 作用域、object kind、detail、DDL、revision cache |
| Hover | qualified symbol resolver 和 object detail renderer |
| Diagnostics | parser/semantic/metadata/execution 统一模型 |
| Execution | ExecutionRequest、source map、exact range |
| Result | revision/fingerprint 绑定 |
20.3 Provider overwrite 风险
当前 set_db_completion_info 会重建 provider。如果直接新增 DBX 风格 provider,schema refresh 可能把它覆盖。
必须改为:
- 一个长期存活的
MergedSqlCompletionProvider; - schema/DB completion info 只更新 metadata source 的数据;
- 外部 provider 作为独立 source;
- 不通过 setter 替换整个 provider object。
21. 文件级实施落点
21.1 crates/db
新增
crates/db/src/sql_editor/document.rs
crates/db/src/sql_editor/dialect.rs
crates/db/src/sql_editor/identifier.rs
crates/db/src/sql_editor/statement_ranges.rs
crates/db/src/sql_editor/analysis.rs
crates/db/src/sql_editor/semantic_model.rs
crates/db/src/sql_editor/diagnostics.rs
crates/db/src/sql_editor/metadata.rs
修改
crates/db/src/sql_editor/sql_tokenizer.rs
crates/db/src/sql_editor/sql_symbol_table.rs
crates/db/src/sql_editor/sql_context_inferrer.rs
crates/db/src/sql_editor/mod.rs
职责:
- 纯 SQL 数据结构和算法;
- 不依赖 GPUI;
- byte offset;
- deterministic unit tests;
- incomplete SQL 保守恢复。
21.2 crates/ui
修改
crates/ui/src/input/state.rs
crates/ui/src/input/element.rs
crates/ui/src/input/lsp/hover.rs
crates/ui/src/input/lsp/completions.rs
crates/ui/src/input/popovers/completion_menu.rs
职责:
- 通用 gutter/decorations;
- hitbox;
- marker event;
- async provider host;
- tooltip/completion rendering;
- 不出现 SQL-specific object types。
可按现有目录风格新增:
crates/ui/src/input/gutter.rs
crates/ui/src/input/decorations.rs
crates/ui/src/input/inline_widget.rs
21.3 crates/db_view
修改
crates/db_view/src/sql_editor.rs
crates/db_view/src/sql_editor_view.rs
职责:
- SQL facade;
- metadata provider;
- analysis scheduling;
- connection scope;
- execution request;
- result integration;
- context menu;
- toolbar/actions。
如文件继续膨胀,建议拆分:
crates/db_view/src/sql_editor/
├── completion_provider.rs
├── hover_provider.rs
├── metadata_cache.rs
├── execution.rs
├── diagnostics.rs
└── actions.rs
21.4 不应修改的边界
- 不要把 SQL parser 逻辑写进
render_sql_editor; - 不要把 SQL-specific marker 写死在
TextElement; - 不要让
SqlEditor自己串行拉全库所有 columns; - 不要让 completion 直接持有 stale connection entity;
- 不要在未协调时覆盖
crates/db/src/streaming_parser.rs的既有修改。
22. 分阶段实施计划
Phase 0:Contract 与测试基线
交付:
SqlTextRangebyte offset contract;SqlDocumentSnapshotrevision;SqlMetadataScopegeneration;QualifiedIdentifier;SqlExecutionRequest;SqlCompletionRequest;- 测试 fixture 与 DBX parity case list。
验收:
- 所有模块只使用显式 range type;
- 不再用不注明单位的
(usize, usize)跨层传 SQL range; - 文档 revision 单调递增;
- scope generation 可观测。
Phase 1:Statement Range Engine
交付:
- quote/comment/dollar quote;
;;GO;DELIMITER;- Oracle
/; - routine/block;
- current statement lookup;
- executable line;
- cache。
验收:
- gutter/current/frame 对同一 cursor 返回同一 statement;
- 不依赖 UI;
- 完成 DBX statement range 测试移植。
Phase 2:通用 GPUI Gutter
交付:
- marker model;
- lane layout;
- independent hitbox;
- icon/state/tooltip;
- mouse event;
- soft-wrap/fold/scroll 行为。
验收:
- 多行 statement 只显示一次;
- 点击不改变 selection/focus;
- 文档变更清 marker;
- UI snapshot/manual test 覆盖。
Phase 3:精确执行
交付:
ExactRange;- selection/current/all priority;
- gutter execution;
- statement identity;
- running/success/error/cancel marker;
- result source fingerprint。
验收:
- gutter 永远执行点击的 statement;
- 当前 cursor 在另一 statement 不影响;
- 编辑文档后旧 marker 不落到新 statement;
- SQL Server batch 正确。
Phase 4:Metadata Model 与 Cache
交付:
- object/column/detail/DDL model;
- scope-aware key;
- generation guard;
- lazy column fetch;
- bounded concurrency;
- cache invalidation。
验收:
- 同名跨 schema table 不串数据;
- connection 切换后旧响应不写 cache;
- 大 schema 不执行逐表串行列加载。
Phase 5:Completion
交付:
- merged provider;
- table/schema/database;
- fields;
- alias-qualified fields;
- CTE/derived table;
- routine/signature;
- snippets;
- keyword;
- wildcard expansion;
- rank/dedupe;
- stale cancellation。
验收:
- 文档测试矩阵中 completion 核心 case 通过;
alias.首屏响应不被全库扫描阻塞;- schema refresh 不覆盖 provider。
Phase 6:Hover 与 Navigation
交付:
- qualified identifier;
- semantic target;
- object detail;
- DDL preview;
- Cmd/Ctrl-click;
- context actions。
验收:
- quoted/multi-part identifier 正确;
- cache scope 正确;
- old hover response 不显示;
- DDL fallback 明确标注非权威。
Phase 7:Diagnostics
交付:
- parser error;
- unknown table/column;
- execution error mapping;
- viewport scheduling;
- run id;
- squiggle/hover detail。
验收:
- 多表歧义不误报;
- metadata incomplete 不误报;
- stale result 不绘制;
- long statement 中段可见仍能诊断。
Phase 8:Editing Utilities
交付:
- format/compress;
- comment/case;
- wildcard expansion action;
- INSERT value hints;
INpaste;- quote caret;
- parameters;
- variables;
- snippets/signature。
Phase 9:Persistence 与 Result Integration
交付:
- selection anchor/head;
- viewport;
- current statement frame;
- result runs;
- statement summary;
- execution source navigation;
- tab activate/deactivate lifecycle。
23. 验收测试矩阵
23.1 Statement ranges
必须覆盖:
- 多条顶层 statement;
- 末尾无分号;
- string 中分号;
- escaped quote;
- double quote/backtick/bracket identifier;
- line/block comment 中分号;
- PostgreSQL dollar quote;
- MyBatis placeholder 与 hash-comment;
- MySQL
DELIMITER; - procedure/function/trigger;
- nested
CASE/BEGIN; - SQL Server
GO,并忽略 string/comment 中的GO; - Oracle/Xugu/GaussDB/SAP HANA block;
- cursor 在 statement 内容;
- 前置缩进;
- 同行分号后空白;
- trailing comment;
- 下一 statement 起点;
- 单独下一行分号;
- 空行/纯注释返回 None;
- Elasticsearch REST request。
DBX 基准:
apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts
23.2 Gutter
必须覆盖:
- 多行 statement 精确映射;
- routine 只有一个 marker;
- placeholder-only line;
- directive 后 executable line;
- SQL Server temp table;
- 普通前导块注释不附着;
- continuation line 不显示 marker;
- delimiter gap;
- trailing whitespace;
- doc revision/dialect 变化重建 cache;
- left mouse only;
- click 不移动 cursor;
- running/success/error state。
DBX 基准:
apps/desktop/src/lib/__tests__/sql/executableStatementRangeCache.spec.ts
注意:DBX 缺少完整 gutter UI render test,Navop 应新增 GPUI element/hitbox 测试。
23.3 Completion
必须覆盖:
- keyword typing trigger;
ORDER BY DESC不误判为 table context;- quoted mixed-case schema/sequence;
- escaped apostrophe;
- dialect-isolated function;
- existing
(不重复; *单表/多表/alias/重复字段/FROM 顺序;- stale/incomplete metadata 拒绝 wildcard;
- qualified schema/database;
- alias-qualified column;
- JOIN;
- CTE/subquery;
- WHERE/INSERT/UPDATE;
- alias generation;
- Oracle no
AS; - explicit completion 在受限模式仍可用;
- snippet;
- routine parameter/signature;
- large catalog performance。
DBX 基准:
apps/desktop/src/lib/__tests__/sql/sqlCompletion.context.spec.tsapps/desktop/src/lib/__tests__/sql/sqlCompletion.signature.spec.tsapps/desktop/src/lib/__tests__/sql/sqlCompletion.snippet.spec.tspackages/app-tests/sqlCompletion.test.tspackages/app-tests/sqlCompletionRoutineParameters.test.tspackages/app-tests/sqlCompletionPerformance.test.ts
23.4 Hover/navigation
必须覆盖:
- no/single/composite PK;
- empty columns;
- SQL Server
varchar(max)/datetime2(7); - precision/scale;
- indexes/comments/constraints;
- partition/distribution;
- sanitize MySQL/MariaDB charset/collation;
- PostgreSQL access-control tail;
- preserve companion statements;
- raw DDL;
- defaults containing comma;
- unsupported type fallback;
- catalog/database/schema cache scope;
- cross-database bare-name rejection;
- statement-local navigation target;
- stale hover response。
DBX 基准:
apps/desktop/src/lib/editor/__tests__/hoverTableSql.spec.tsapps/desktop/src/lib/__tests__/sql/sqlNavigation.spec.ts
23.5 Diagnostics
必须覆盖:
- missing table/column;
- empty/incomplete metadata;
- alias;
- correlated subquery;
- nested scope;
- multi-table ambiguity;
- parser line/column;
- severity/message/span;
- viewport complete statement;
- long statement middle viewport;
- SQL Server
GObatch; - procedure/function/Oracle PL/SQL skip;
- Mongo/Elasticsearch skip;
- stale document;
- execution range base offset。
DBX 基准:
packages/app-tests/sqlSemanticDiagnostics.test.ts
23.6 Formatting
必须覆盖:
- whitespace compress;
- comment handling;
- preserve strings/identifiers;
- empty input;
- already compressed;
- executable comma placement;
- unclosed block comment;
- MySQL executable/versioned/optimizer comments;
- backslash escape;
#comment;- MySQL
--rule; - PostgreSQL dollar quote/nested comment/E-string;
- SQL Server bracket identifier。
DBX 基准:
packages/app-tests/sqlFormatter.test.ts
23.7 Editing
必须覆盖:
- quote caret;
- large paste;
- text edits;
- newline indentation;
- line/block comments;
- selection case;
INpaste;- INSERT value hints;
- trimmed selection;
- folding;
- context-menu target ordering;
- table/column drag-drop;
- parameters;
- variables;
- editable query conservative rejection。
DBX 基准:
apps/desktop/src/lib/__tests__/sql/sqlQuoteCaret.spec.tsapps/desktop/src/lib/__tests__/sql/sqlSelectionCase.spec.tsapps/desktop/src/lib/__tests__/sql/sqlInListPaste.spec.tsapps/desktop/src/lib/__tests__/editor/*apps/desktop/src/components/editor/__tests__/QueryEditorContextMenu.spec.tspackages/app-tests/sqlParameters.spec.tspackages/app-tests/sqlVariables.spec.tspackages/app-tests/sqlAnalysis.test.tspackages/app-tests/queryEditorTableDrop.test.ts
23.8 Execution/result
必须覆盖:
- selection/current/all/exact range;
- Mongo current command;
- SQL Server
GObatch; - trailing whitespace;
- current frame 与 gutter range 一致;
- stale marker;
- cancel;
- error source mapping;
- new result tab;
- result default focus;
- result source double-click。
DBX 基准:
packages/app-tests/sqlExecutionTarget.test.tspackages/app-tests/sqlBatchScript.test.tsapps/desktop/src/lib/__tests__/sql/currentStatementFrame.spec.tspackages/app-tests/sqlserverResultFocus6189.test.ts
24. 性能目标
以下为 Navop 建议目标,不是 DBX 源码中明确 SLA。
24.1 编辑输入
- 普通 keypress 的同步 SQL 工作:P95 < 4ms;
- UI thread 不进行远端 metadata I/O;
- 不在每次 keypress 全文重建所有 columns;
- statement range scanner 对普通文档 O(n),cache 后 cursor lookup O(log n);
- 100k 字符文档滚动无明显卡顿;
- 1M 字符文档仍可编辑,重分析按 viewport/statement。
24.2 Completion
- local semantic/keyword candidates:P95 < 30ms;
- cache-hit table/column completion:P95 < 50ms;
- remote metadata 不阻塞首批 local popup;
- popup 最大 candidates 有上限;
- large schema 搜索分页;
- 每个 editor 同类 remote request 可合并/取消。
24.3 Hover
- cache hit:目标 50ms 内;
- cache miss:显示 loading skeleton 或延迟出现;
- pointer 移动后旧请求立即逻辑失效;
- DDL formatting 在 background task。
24.4 Diagnostics
- 默认 debounce 500ms;
- viewport analysis 优先;
- metadata enrichment bounded concurrency;
- 不因 diagnostics 阻塞输入或 completion。
25. 高风险与强制规则
25.1 Provider overwrite
风险:set_db_completion_info 重建 provider,导致新 provider 被 schema refresh 覆盖。
强制规则:provider 长期存活,更新 source 数据,不替换 provider。
25.2 Stale async
风险:旧 completion/hover/metadata/diagnostics 返回后污染新文档。
强制规则:所有 async response 检查 request id + revision + scope generation。
25.3 Statement splitter divergence
风险:gutter 显示 A,Run Current 执行 B,driver 再切成 C。
强制规则:编辑器所有 target 使用同一 snapshot;driver 接收已解析 execution request,除协议必要外不二次猜 cursor statement。
25.4 Offset mismatch
风险:Rust byte、Rope char、UTF-16 混用,在中文/emoji 前后错位。
强制规则:内部 byte offset,边界显式转换,测试包含中文和 emoji。
25.5 Multi-database semantics
必须显式处理:
- Oracle schema;
- MySQL
database.table; - PostgreSQL
database.schema.table; uses_schema_as_database;- IPC schema switch;
- session-scoped current database/schema。
25.6 Quoted identifier
不能无条件 lowercase:
"Foo";`Foo`;[Foo]。
25.7 Large schema
禁止:
- 连接时逐表串行加载 columns;
- completion 每次遍历无限 catalog;
- cache key 只有 table name;
- popup 等待全量 remote 才显示。
25.8 Hover DDL
禁止:
- metadata fallback 冒充 backend DDL;
- formatter parse error 后返回空;
- sanitize 改变 statement 语义;
- 在 hover 失败时弹打断用户的全局 toast。
25.9 Right-click stale target
菜单 target 必须在打开前同步,异步菜单 action 绑定本次 context-menu identity。
25.10 IME
composition 期间不得触发会替换 composition range 的 completion/edit action。
25.11 Result marker
旧 result 只能绑定旧 revision/fingerprint,不能按相同行号直接挂到新文档。
25.12 Resource leak
hover、popover、timer、pointer/scroll/window listener、background task 在 deactivate/destroy 时必须清理。
26. Definition of Done
只有满足以下全部条件,才可认为“DBX 风格 SQL 编辑器核心改造”完成。
26.1 Statement 与执行
- 每条 executable statement 起始行显示运行图标;
- 多行 SQL 只显示一次;
- comment/string/dialect delimiter 不误切;
- gutter 精确执行且不移动 cursor;
- current/all/selection/exact range 规则一致;
- current statement frame 与 gutter range 一致;
- execution marker 有 running/success/error/cancel;
- 编辑后旧 marker 不错位。
26.2 Completion
- table/schema/database;
- field completion;
- alias-qualified fields;
- JOIN/INSERT/UPDATE context;
- CTE/derived table columns;
- projection alias dialect rules;
- routines/signatures;
- keyword/snippet;
SELECT *safe expansion;- rank/filter/dedupe;
- stale cancellation;
- large schema 不阻塞。
26.3 Hover/navigation
- qualified/quoted identifier;
- table/view/materialized view/routine;
- columns/type/nullability/default/comment;
- PK/index/FK;
- backend DDL;
- marked fallback DDL;
- scope-safe cache;
- Cmd/Ctrl-click 和 context actions;
- stale hover 不显示。
26.4 Diagnostics/editing
- parser error;
- unknown table/column;
- execution error mapping;
- viewport/stale guard;
- formatter/compress;
- quote caret;
INpaste;- case/comment actions;
- parameters/variables;
- INSERT value hints。
26.5 Lifecycle/quality
- document revision contract;
- metadata generation contract;
- byte offset contract;
- deactivate/activate/destroy cleanup;
- DBX 边界测试已移植;
- GPUI gutter hitbox/render test;
- 中文/emoji offset test;
- large catalog performance test;
- 没有覆盖用户现有
streaming_parser.rs修改。
27. DBX 源码索引
27.1 Editor 主组件与布局
dbx/apps/desktop/src/components/editor/QueryEditor.vuedbx/apps/desktop/src/components/layout/EditorToolbar.vuedbx/apps/desktop/src/components/layout/ContentArea.vue
27.2 Statement 与 execution
dbx/apps/desktop/src/lib/sql/sqlStatementRanges.tsdbx/apps/desktop/src/lib/sql/executableStatementRangeCache.tsdbx/apps/desktop/src/lib/sql/statementDelimiter.tsdbx/apps/desktop/src/lib/sql/sqlExecutionTarget.tsdbx/apps/desktop/src/lib/sql/currentStatementFrame.tsdbx/apps/desktop/src/lib/editor/codemirrorStatementGutter.tsdbx/apps/desktop/src/lib/editor/codemirrorCurrentStatementFrameLayer.ts
27.3 Completion 与 semantic
dbx/apps/desktop/src/lib/sql/sqlCompletion.tsdbx/apps/desktop/src/lib/sql/sqlCompletionLookupTarget.tsdbx/apps/desktop/src/lib/sql/sqlSnippetTemplates.tsdbx/apps/desktop/src/lib/sql/sqlSyntaxTreeWindow.tsdbx/apps/desktop/src/lib/sql/semantic/completion.tsdbx/apps/desktop/src/lib/sql/semantic/model.tsdbx/apps/desktop/src/lib/sql/semantic/references.tsdbx/apps/desktop/src/lib/metadata/completionTreeIndex.tsdbx/apps/desktop/src/stores/connectionStore.tsdbx/crates/dbx-core/src/types.rsdbx/crates/dbx-core/src/schema.rs
27.4 Hover/navigation
dbx/apps/desktop/src/lib/sql/queryCursorTableTarget.tsdbx/apps/desktop/src/lib/sql/sqlNavigation.tsdbx/apps/desktop/src/lib/editor/hoverTableSql.tsdbx/apps/desktop/src/lib/editor/sqlHoverLayout.tsdbx/apps/desktop/src/lib/editor/sqlSignatureTooltip.ts
27.5 Diagnostics
dbx/apps/desktop/src/lib/sql/semantic/diagnostics.tsdbx/apps/desktop/src/lib/sql/sqlDiagnostics.ts
27.6 编辑辅助
dbx/apps/desktop/src/lib/sql/insertValueHints.tsdbx/apps/desktop/src/lib/editor/codemirrorInsertValueHints.tsdbx/apps/desktop/src/lib/sql/sqlQuoteCaret.tsdbx/apps/desktop/src/lib/sql/sqlInListPaste.tsdbx/apps/desktop/src/lib/sql/sqlSelectionCase.tsdbx/apps/desktop/src/lib/sql/sqlParameters.tsdbx/apps/desktop/src/lib/sql/sqlVariables.tsdbx/apps/desktop/src/components/editor/SqlParameterDialog.vuedbx/apps/desktop/src/lib/sql/sqlAnalysis.ts
27.7 Format/history/save
dbx/apps/desktop/src/lib/sql/sqlFormatter.tsdbx/apps/desktop/src/lib/sql/sqlFormatterConfig.tsdbx/apps/desktop/src/lib/sql/autoFormat.tsdbx/apps/desktop/src/stores/historyStore.tsdbx/apps/desktop/src/stores/savedSqlStore.tsdbx/apps/desktop/src/lib/sql/sqlFileOpen.tsdbx/apps/desktop/src/composables/useExternalSqlFileChanges.ts
28. Navop 源码索引
navop/crates/db/src/sql_editor/sql_tokenizer.rsnavop/crates/db/src/sql_editor/sql_symbol_table.rsnavop/crates/db/src/sql_editor/sql_context_inferrer.rsnavop/crates/db/src/streaming_parser.rsnavop/crates/db_view/src/sql_editor.rsnavop/crates/db_view/src/sql_editor_view.rsnavop/crates/ui/src/input/state.rsnavop/crates/ui/src/input/element.rsnavop/crates/ui/src/input/lsp/hover.rsnavop/crates/ui/src/input/lsp/completions.rsnavop/crates/ui/src/input/popovers/completion_menu.rs
29. 推荐给实施 Agent 的执行方式
- 不要从 UI 图标开始孤立实现;先完成 Phase 0 contract;
- Phase 1 先移植 statement range tests,再实现 scanner;
- Phase 2 的 gutter 必须作为 GPUI Input 通用能力,不写死 SQL;
- Phase 3 后即可交付用户最直观的“每条完整 SQL 左侧运行”能力;
- metadata 和 completion 分开做,先改 provider 生命周期,避免后续被覆盖;
- 每个 async 功能先写 stale-response test,再接远端;
- hover 首先实现 cache-hit table detail,再逐步接 DDL 和 navigation;
- diagnostics 必须在 statement/semantic snapshot 稳定后实现;
- 每个 phase 都应保持 editor 可运行,不做大爆炸重写;
- 所有涉及
streaming_parser.rs的改动先确认并保留当前工作树中的既有修改。
最终架构的判断标准不是“看起来像 DBX”,而是:
- SQL statement 语义一致;
- 异步结果不会错位;
- qualified/quoted identifier 不丢信息;
- 大 schema 不阻塞;
- execution、completion、hover、diagnostics 共用统一 snapshot;
- GPUI Input 基础设施仍然是通用、可复用的。