查询语言

类型化 SQL:
JOIN、DML 与 Heap DDL。

查询语言为有限的原生子集,包含解析器、名义类型检查、三值逻辑、受 WAL 保护的 DML,以及有界的 Heap DDL。它不是完整的 SQL 方言。

类别当前支持当前不支持
SELECT限定 / 非限定列、通配投影、LIMIT、类型化表达式、AS 别名、后缀 :: 转换DISTINCT、窗口函数、投影中的子查询
FROM / JOINAS 与简写别名、链式 INNER JOIN … ON、NestedLoopJoin、HashJoin、IndexJoin外连接、USING、连接重排、merge join
谓词AND / OR / NOT、比较、IS NULL、括号IN / BETWEEN / LIKE、子查询
DML显式列清单或声明顺序的单行 INSERT、UPDATE、DELETE、可选 WHERE默认值、RETURNING、UPSERT
ORDER BY多源列键、ASC / DESC、NULLS FIRST / LAST别名、序号、任意排序表达式
聚合COUNT(*) / COUNT / SUM / MIN / MAX、源列 GROUP BYHAVING、DISTINCT 聚合、分组表达式、ROLLUP
DDLHeap CREATE TABLE(物理类型 v2)、DROP TABLE、ALTER TABLE(改名、可空 ADD、DROP、SET/DROP NOT NULL)、CREATE/DROP INDEXPRIMARY KEY / UNIQUE / FK、IF EXISTS、限定名、LSM/范围组合、通用 ALTER COLUMN TYPE

名义类型

Schema 列同时保留物理表示与可选的名义语义类型。HIR 在比较中要求名义兼容,因此上下文 NULL 类型也不能让 UserId = TeamId 合法。自连接通过查询局部的 RelationBindingId 区分同一 TableId 的两次出现。

physical: UINT64
semantic: UserId

UserId ≠ TeamId   even when both are u64

NULL 是数据库值

数据库 NULL 是显式的 ScalarValue::Null。Rust Option 留给缺席的子句或元数据。比较遇到 NULL 得到 UNKNOWN;IS NULL / IS NOT NULL 才是显式测试。AND / OR / NOT 使用 SQL 三值逻辑。WHERE 与 JOIN 的 ON 只保留 TRUE,FALSE 与 UNKNOWN 都被拒绝。

Bool(true)  → TRUE
Bool(false) → FALSE
NULL        → UNKNOWN

NULL = NULL     → UNKNOWN
NULL IS NULL    → TRUE

JOIN

别名会隐藏底层表名。限定列经由暴露的关系名解析;非限定列仅在恰好一个可见关系提供该名时被接受。每个 ON 能看见完整左子树与当前右关系,但不能看见更后的连接。默认算子为 NestedLoopJoin。ANALYZE 之后,两个扫描上的简单等值 INNER JOIN 在代价严格更低时可选 HashJoin 或 Index Nested-Loop Join。算子均按确定性的左主、右次顺序保留重复。

SELECT e.name, m.name
FROM employees e
JOIN employees m ON e.manager_id = m.id
WHERE e.active IS NOT NULL
ORDER BY e.name ASC NULLS LAST
LIMIT 20

DML

类型化 DML 使用与堆写入相同的编译器、事务、整页 WAL、回滚与恢复路径。Database::execute 返回查询行或显式 AffectedRows(u64);query 拒绝变更语句。省略的可空 INSERT 列赋值为 NULL;省略的非空列将被拒绝。UPDATE 基于原始行求值全部右侧,因此 SET a = b, b = a 会交换两列。

INSERT INTO users (id, name) VALUES (1, 'Ada');
UPDATE users SET name = 'Ada Lovelace' WHERE id = 1;
DELETE FROM users WHERE name IS NULL;

DDL

Heap 上的 CREATE TABLE、DROP TABLE、ALTER TABLE 与 CREATE/DROP INDEX 是事务性的。ALTER 支持改表名 / 列名、可空 ADD、受限 DROP 与 SET/DROP NOT NULL。后缀 :: 转换为精确宽度,没有隐式数值拓宽。LSM 与分区表不在该 SQL DDL 范围内。

CREATE TABLE events (
    id BIGINT NOT NULL,
    payload BYTEA NOT NULL
);
ALTER TABLE events ADD COLUMN note TEXT;
SELECT id::TEXT, payload FROM events;
DROP TABLE events;

排序与聚合

普通计划是 Scan/Join → Filter → Sort → Project → Limit。聚合计划是 Scan/Join → Filter → Aggregate → Limit。键在投影之前、对着完整 FROM / JOIN 作用域解析,所以查询可以按它不返回的列排序。

COUNT(*) 计行;COUNT(column) 忽略 NULL。单独的全局 COUNT(column) 在 SeqScan 上可统计存在性而不物化行。数值 SUM 使用受检算术,并剥去名义含义。MIN / MAX 保留输入 SemanticType。分组键上的 NULL 共享一组,这与表达式里 NULL = NULL 仍为 UNKNOWN 不同。带 GROUP BY 的查询当前拒绝 ORDER BY。

SELECT team_id, COUNT(*), SUM(score), MAX(score)
FROM scores
GROUP BY team_id

索引与 ANALYZE

create_index 与 SQL CREATE INDEX 在事务性回填后注册非唯一单列 Heap BTree。DROP INDEX 注销该注册。随后的堆与 SQL DML 会维护已注册索引。符合条件的等值与 IS NULL 谓词可选择点查 IndexScan;经过分析的双侧 Int64/UInt64 边界可选择范围 IndexScan。ANALYZE 为显式操作,DML 不会自动维护统计。

create_index(table, column)
    → transactional backfill
    → register in IndexCatalog
    → DML maintains the index
    → ANALYZE writes a cost snapshot
    → planner may choose IndexScan

跨存储写入

create_tables 仍按表组合一个堆文件。范围分区表以及混合 Heap+LSM 目录经协调日志提交。派生列存投影不是权威存储。不提供并发写者。不提供可串行化隔离。