release: v0.4.1 — Aria 级联/ALTER/clearAll + 流式查询/派生表 + 正确性加固
新增: - AriaEngine 外键级联(CASCADE/SET NULL/RESTRICT)+ clearAll() 重置 API - 引擎级 alterTable:Aria DROP COLUMN 重写存储行 + schema 持久化 - 流式查询 queryStream / findStream(LSM 惰性扫描不物化) - FROM 派生表 / 多列 ON 哈希连接 / COUNT(DISTINCT) / NULLS FIRST/LAST - 普通列别名 + ORDER BY 别名 + 无表查询 + 字符串常量列 - 演示页引擎切换器(Memory/Aria)+ 预设自动重置 修复: - Aria WAL DROP_TABLE 崩溃恢复(删表复活)+ 恢复后 WAL 截断 - Memory update/delete 索引维护(unique 约束绕过) - 关联 EXISTS 绑定失效 / HAVING 标量子查询 / INSERT SELECT 位置错位 - 裸布尔列条件(WHERE done / CASE WHEN done) - Aria $in 重复行 / JOIN 主表 WHERE 下推 / DROP INDEX 报错 - ORDER BY/GROUP BY/SELECT 表前缀列 + SQL '' 标准转义 质量:894 测试 · 47 套件 · 81.5% 覆盖率
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>⚡ 性能基准 — MetonaSqlark v0.3.2</title>
|
||||
<title>⚡ 性能基准 — MetonaSqlark v0.4.1</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='8' fill='%236366f1'/><text x='16' y='22' text-anchor='middle' font-size='20' fill='white'>◈</text></svg>">
|
||||
<style>
|
||||
:root {
|
||||
|
||||
+121
-54
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>🧪 在线演示 — MetonaSqlark v0.3.2</title>
|
||||
<title>🧪 在线演示 — MetonaSqlark v0.4.1</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='8' fill='%236366f1'/><text x='16' y='22' text-anchor='middle' font-size='20' fill='white'>◈</text></svg>">
|
||||
<style>
|
||||
:root {
|
||||
@@ -84,13 +84,15 @@
|
||||
<a href="demo.html" class="nav-active">演示</a>
|
||||
<a href="benchmark.html">基准</a>
|
||||
</nav>
|
||||
<div class="status"><span class="dot"></span> Memory 模式 — v0.3.2</div>
|
||||
<div class="status"><span class="dot" id="engine-dot"></span> <span id="engine-status">Memory</span> 模式 — v0.4.1</div>
|
||||
<button class="btn btn-preset" onclick="switchEngine('memory')" id="btn-memory" style="margin:6px 4px 6px 0;padding:6px 12px;">⚡ Memory</button>
|
||||
<button class="btn btn-preset" onclick="switchEngine('aria')" id="btn-aria" style="margin:6px 0;padding:6px 12px;color:#ec4899;border-color:#ec4899;">🌲 Aria</button>
|
||||
</header>
|
||||
|
||||
<div class="main">
|
||||
<div class="editor-panel">
|
||||
<div class="editor-area">
|
||||
<textarea id="sql-input" placeholder="输入 SQL 语句... SELECT * FROM users; INSERT INTO users VALUES ('4', 'Diana', 'diana@test.com', 28); SELECT u.name, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id;">-- 🚀 MetonaSqlark v0.3.2 在线演示
|
||||
<textarea id="sql-input" placeholder="输入 SQL 语句... SELECT * FROM users; INSERT INTO users VALUES ('4', 'Diana', 'diana@test.com', 28); SELECT u.name, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id;">-- 🚀 MetonaSqlark v0.4.1 在线演示
|
||||
-- 已预置 users / orders / products 表数据
|
||||
-- 新特性: ALTER TABLE · TRUNCATE TABLE · WAL同步 · MVCC · SQL注入防护
|
||||
|
||||
@@ -128,6 +130,7 @@
|
||||
<button class="btn btn-preset" onclick="loadPreset('exists')">🔍 EXISTS</button>
|
||||
<button class="btn btn-preset" onclick="loadPreset('index')">🗂 索引</button>
|
||||
<button class="btn btn-preset" onclick="loadPreset('multistmt')">📜 多语句/事务</button>
|
||||
<button class="btn btn-preset" onclick="loadPreset('v040')" style="color:#22c55e;border-color:#22c55e;">🚰 v0.4.0 新特性</button>
|
||||
<button class="btn btn-preset" onclick="loadPreset('aria')" style="color:#ec4899;border-color:#ec4899;">🌲 Aria</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -161,57 +164,84 @@ const rowCount = document.getElementById('row-count');
|
||||
const sqlInput = document.getElementById('sql-input');
|
||||
|
||||
// Init database
|
||||
let currentEngine = 'memory';
|
||||
|
||||
async function initDB() {
|
||||
try {
|
||||
db = new DBClass({ name: 'demo', mode: 'memory' });
|
||||
const engine = currentEngine;
|
||||
// 关闭旧实例(预设重置/引擎切换时数据回到初始状态)
|
||||
if (db) { try { await db.close(); } catch { /* ignore */ } }
|
||||
db = new DBClass({ name: 'demo', mode: engine });
|
||||
await db.init();
|
||||
|
||||
// Create tables
|
||||
await db.defineTable('users', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
name: { type: 'string', required: true },
|
||||
email: { type: 'string' },
|
||||
age: { type: 'number', default: 0 },
|
||||
});
|
||||
await db.defineTable('orders', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
user_id: { type: 'string' },
|
||||
product: { type: 'string' },
|
||||
amount: { type: 'number' },
|
||||
quantity: { type: 'number', default: 1 },
|
||||
});
|
||||
await db.defineTable('products', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
name: { type: 'string', required: true },
|
||||
price: { type: 'number', default: 0 },
|
||||
category: { type: 'string' },
|
||||
});
|
||||
// v0.4.1: Aria 引擎持久化 — 每次加载清空上次演示数据,保证演示确定性
|
||||
if (engine === 'aria' && typeof db.getEngine().clearAll === 'function') {
|
||||
await db.getEngine().clearAll();
|
||||
}
|
||||
|
||||
// Seed data
|
||||
await db.table('users').insertMany([
|
||||
{ id: '1', name: 'Alice', email: 'alice@demo.com', age: 30 },
|
||||
{ id: '2', name: 'Bob', email: 'bob@demo.com', age: 25 },
|
||||
{ id: '3', name: 'Charlie', email: 'charlie@demo.com', age: 35 },
|
||||
{ id: '4', name: 'Diana', email: 'diana@demo.com', age: 28 },
|
||||
{ id: '5', name: 'Eve', email: 'eve@demo.com', age: 22 },
|
||||
]);
|
||||
await db.table('orders').insertMany([
|
||||
{ id: 'o1', user_id: '1', product: 'Laptop', amount: 1200, quantity: 1 },
|
||||
{ id: 'o2', user_id: '1', product: 'Mouse', amount: 50, quantity: 2 },
|
||||
{ id: 'o3', user_id: '2', product: 'Keyboard', amount: 150, quantity: 1 },
|
||||
{ id: 'o4', user_id: '3', product: 'Monitor', amount: 400, quantity: 1 },
|
||||
{ id: 'o5', user_id: '3', product: 'Cable', amount: 20, quantity: 3 },
|
||||
]);
|
||||
await db.table('products').insertMany([
|
||||
{ id: 'p1', name: 'Laptop', price: 1200, category: 'Electronics' },
|
||||
{ id: 'p2', name: 'Mouse', price: 50, category: 'Accessories' },
|
||||
{ id: 'p3', name: 'Keyboard', price: 150, category: 'Accessories' },
|
||||
]);
|
||||
await seedDemoData(db);
|
||||
renderInfo(`✅ ${engine === 'aria' ? '🌲 AriaEngine(LSM-Tree + WAL + MVCC)' : '⚡ Memory'} 引擎已就绪`);
|
||||
} catch (e) {
|
||||
renderError('数据库初始化失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 建表 + 种子数据(每次预设重置/引擎切换后重建,保证演示可预期)
|
||||
async function seedDemoData(db) {
|
||||
await db.defineTable('users', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
name: { type: 'string', required: true },
|
||||
email: { type: 'string' },
|
||||
age: { type: 'number', default: 0 },
|
||||
});
|
||||
await db.defineTable('orders', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
user_id: { type: 'string' },
|
||||
product: { type: 'string' },
|
||||
amount: { type: 'number' },
|
||||
quantity: { type: 'number', default: 1 },
|
||||
});
|
||||
await db.defineTable('products', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
name: { type: 'string', required: true },
|
||||
price: { type: 'number', default: 0 },
|
||||
category: { type: 'string' },
|
||||
});
|
||||
|
||||
// Seed data
|
||||
await db.table('users').insertMany([
|
||||
{ id: '1', name: 'Alice', email: 'alice@demo.com', age: 30 },
|
||||
{ id: '2', name: 'Bob', email: 'bob@demo.com', age: 25 },
|
||||
{ id: '3', name: 'Charlie', email: 'charlie@demo.com', age: 35 },
|
||||
{ id: '4', name: 'Diana', email: 'diana@demo.com', age: 28 },
|
||||
{ id: '5', name: 'Eve', email: 'eve@demo.com', age: 22 },
|
||||
]);
|
||||
await db.table('orders').insertMany([
|
||||
{ id: 'o1', user_id: '1', product: 'Laptop', amount: 1200, quantity: 1 },
|
||||
{ id: 'o2', user_id: '1', product: 'Mouse', amount: 50, quantity: 2 },
|
||||
{ id: 'o3', user_id: '2', product: 'Keyboard', amount: 150, quantity: 1 },
|
||||
{ id: 'o4', user_id: '3', product: 'Monitor', amount: 400, quantity: 1 },
|
||||
{ id: 'o5', user_id: '3', product: 'Cable', amount: 20, quantity: 3 },
|
||||
]);
|
||||
await db.table('products').insertMany([
|
||||
{ id: 'p1', name: 'Laptop', price: 1200, category: 'Electronics' },
|
||||
{ id: 'p2', name: 'Mouse', price: 50, category: 'Accessories' },
|
||||
{ id: 'p3', name: 'Keyboard', price: 150, category: 'Accessories' },
|
||||
]);
|
||||
}
|
||||
|
||||
// v0.4.1: 切换存储引擎(重建数据库实例)
|
||||
async function switchEngine(engine) {
|
||||
if (engine === currentEngine) return;
|
||||
currentEngine = engine;
|
||||
document.getElementById('btn-memory').style.opacity = engine === 'memory' ? '1' : '0.6';
|
||||
document.getElementById('btn-aria').style.opacity = engine === 'aria' ? '1' : '0.6';
|
||||
document.getElementById('engine-status').textContent = engine === 'aria' ? '🌲 Aria' : '⚡ Memory';
|
||||
document.getElementById('engine-dot').style.background = engine === 'aria' ? '#ec4899' : '';
|
||||
renderInfo(`⏳ 正在初始化 ${engine === 'aria' ? 'Aria' : 'Memory'} 引擎…`);
|
||||
await initDB();
|
||||
}
|
||||
|
||||
// Run SQL
|
||||
async function runQuery() {
|
||||
const sql = sqlInput.value.trim();
|
||||
@@ -316,6 +346,10 @@ function renderSuccess(msg) {
|
||||
resultArea.innerHTML = `<div class="success-box">${msg}</div>`;
|
||||
}
|
||||
|
||||
function renderInfo(msg) {
|
||||
resultArea.innerHTML = `<div class="success-box" style="color:#22c55e;border-color:#22c55e;">${msg}</div>`;
|
||||
}
|
||||
|
||||
function clearResults() {
|
||||
resultArea.innerHTML = `<div class="empty-state"><div class="icon">⚡</div><div>结果已清空</div></div>`;
|
||||
updateRowCount(0);
|
||||
@@ -518,11 +552,13 @@ SELECT COUNT(*) as total FROM temp_logs;
|
||||
|
||||
-- 清理
|
||||
DROP TABLE temp_logs;`,
|
||||
aria: `-- 🌲 AriaEngine 演示 (v0.2.5 → v0.3.2)
|
||||
-- AriaEngine: LSM-Tree 自研存储引擎
|
||||
-- 支持 LSM-Tree · WAL CRC同步 · MVCC版本链 · BloomFilter · 二级索引 · AES-GCM · 836测试
|
||||
aria: `-- 🌲 AriaEngine 演示 (v0.4.1)
|
||||
-- 点击右上角「🌲 Aria」按钮切换数据库引擎到 AriaEngine
|
||||
-- 当前数据库即运行在 Aria 引擎上(LSM-Tree · WAL 崩溃恢复 · MVCC · BloomFilter)
|
||||
-- 基础 CRUD 与 Memory 引擎完全兼容
|
||||
|
||||
-- 基础 CRUD 完全兼容
|
||||
-- 当前引擎确认
|
||||
-- (内存中 Aria 引擎实例,数据经 WAL + SSTable 持久化到 IndexedDB)
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
id STRING PRIMARY KEY,
|
||||
title STRING NOT NULL,
|
||||
@@ -556,8 +592,9 @@ DROP TABLE temp_logs;`,
|
||||
-- • Buffer Pool: SSTable LRU 缓存 (256页 ~ 1MB) ✅ 已生效
|
||||
-- • Bloom Filter: FNV-1a + Murmur 双哈希
|
||||
-- • 二级索引: 每列独立 LSM + 动态 CREATE INDEX
|
||||
-- • 外键级联: CASCADE / SET NULL / RESTRICT (v0.4.1)
|
||||
|
||||
-- 生产环境: mode: 'aria' 激活自研引擎
|
||||
-- 生产环境 API(与演示页右上角切换等价)
|
||||
-- const db = await MetonaSqlark.create({
|
||||
-- name: 'my-app', mode: 'aria'
|
||||
-- });`,
|
||||
@@ -634,10 +671,10 @@ JOIN orders o ON u.id = o.user_id
|
||||
WHERE EXISTS (SELECT 1 FROM orders o2 WHERE o2.user_id = u.id AND o2.amount > 100);`,
|
||||
index: `-- 🗂 动态索引 CREATE / DROP INDEX (v0.3.0)
|
||||
|
||||
-- 为 orders.user_id 创建索引
|
||||
-- 为 orders.user_id 创建索引(已有数据自动回填)
|
||||
CREATE INDEX idx_orders_user ON orders (user_id);
|
||||
|
||||
-- 索引查找(走二级索引)
|
||||
-- 索引查找(v0.4.1: JOIN 主表 WHERE 条件下推到引擎,真正走二级索引)
|
||||
SELECT u.name, o.product, o.amount
|
||||
FROM orders o JOIN users u ON u.id = o.user_id
|
||||
WHERE o.user_id = '1';
|
||||
@@ -646,7 +683,10 @@ WHERE o.user_id = '1';
|
||||
DROP INDEX idx_orders_user ON orders (user_id);
|
||||
|
||||
-- 删除后回退全表扫描(结果不变)
|
||||
SELECT * FROM orders WHERE user_id = '3';`,
|
||||
SELECT * FROM orders WHERE user_id = '3';
|
||||
|
||||
-- DROP 不存在的索引会报错(INDEX_NOT_FOUND)
|
||||
-- DROP INDEX idx_nonexist ON orders (user_id);`,
|
||||
multistmt: `-- 📜 多语句 + 事务语句 (v0.3.0)
|
||||
|
||||
-- 分号分隔的多语句一次执行
|
||||
@@ -667,11 +707,35 @@ BEGIN;
|
||||
INSERT INTO audit VALUES ('a4', 'will be committed');
|
||||
COMMIT;
|
||||
SELECT COUNT(*) as total FROM audit;`,
|
||||
v040: `-- 🚰 v0.4.0 新特性
|
||||
|
||||
-- 派生表:FROM (SELECT ...) 子查询作为行源
|
||||
SELECT category, total FROM (
|
||||
SELECT category, SUM(price) AS total FROM products GROUP BY category
|
||||
) AS t WHERE total > 100 ORDER BY total DESC;
|
||||
|
||||
-- COUNT(DISTINCT col):去重计数
|
||||
SELECT COUNT(DISTINCT category) AS categories FROM products;
|
||||
|
||||
-- NULLS FIRST / LAST:NULL 排序位置控制
|
||||
SELECT name FROM users ORDER BY age ASC NULLS FIRST LIMIT 3;
|
||||
|
||||
-- 普通列别名 + ORDER BY 别名
|
||||
SELECT name AS n FROM users ORDER BY n DESC;
|
||||
|
||||
-- SQL 标准 '' 字符串转义
|
||||
SELECT 'it''s a test' AS escaped;
|
||||
|
||||
-- 哈希连接(等值 ON 走 O(N+M);多列等值 ON 同样支持)
|
||||
SELECT u.name, o.product FROM users u
|
||||
INNER JOIN orders o ON o.user_id = u.id;`,
|
||||
};
|
||||
|
||||
function loadPreset(name) {
|
||||
// v0.4.1: 点击预设前自动重置数据(前序预设可能修改/删除种子数据,重置保证每个预设可预期演示)
|
||||
async function loadPreset(name) {
|
||||
if (presets[name]) {
|
||||
sqlInput.value = presets[name];
|
||||
await initDB();
|
||||
runQuery();
|
||||
}
|
||||
}
|
||||
@@ -685,8 +749,11 @@ document.addEventListener('keydown', e => {
|
||||
});
|
||||
|
||||
// Boot
|
||||
document.getElementById('btn-memory').style.opacity = '1';
|
||||
document.getElementById('btn-aria').style.opacity = '0.6';
|
||||
document.getElementById('engine-status').textContent = '⚡ Memory';
|
||||
initDB().then(() => {
|
||||
console.log('✅ MetonaSqlark v0.3.2 demo ready');
|
||||
console.log('✅ MetonaSqlark v0.4.1 demo ready');
|
||||
setTimeout(runQuery, 300);
|
||||
}).catch(err => {
|
||||
renderError('初始化失败: ' + err.message);
|
||||
|
||||
+19
-3
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>📖 API 文档 — MetonaSqlark v0.3.2</title>
|
||||
<title>📖 API 文档 — MetonaSqlark v0.4.1</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='8' fill='%236366f1'/><text x='16' y='22' text-anchor='middle' font-size='20' fill='white'>◈</text></svg>">
|
||||
<style>
|
||||
:root {
|
||||
@@ -203,6 +203,21 @@ db.<span class="f">isReady</span>(); <span class="c">// true</span>
|
||||
|
||||
<h2 id="sql-query">🔍 SQL 查询</h2>
|
||||
<p><code>db.query(sql)</code> — 执行标准 SQL 字符串,返回查询结果。</p>
|
||||
<p><code>db.queryStream(sql, onRow)</code> — 流式查询(v0.4.0):逐行回调不物化结果集,大表友好。支持简单 SELECT(WHERE/LIMIT/OFFSET/列投影);JOIN/GROUP BY/UNION/聚合/ORDER BY 自动回退物化。</p>
|
||||
|
||||
<pre><span class="c">// 流式查询 — 大表逐行处理</span>
|
||||
<span class="k">let</span> count = <span class="n">0</span>;
|
||||
<span class="k">await</span> db.<span class="f">queryStream</span>(<span class="s">"SELECT * FROM logs WHERE level = 'error'"</span>, (row) => {
|
||||
count++;
|
||||
processRow(row);
|
||||
});
|
||||
|
||||
<span class="c">// 派生表 / COUNT(DISTINCT) / NULLS 排序(v0.4.0)</span>
|
||||
<span class="k">const</span> top = <span class="k">await</span> db.<span class="f">query</span>(<span class="s">`SELECT dept, total FROM
|
||||
(SELECT dept, SUM(salary) AS total FROM emp GROUP BY dept) AS t
|
||||
WHERE total > 100 ORDER BY total DESC`</span>);
|
||||
<span class="k">await</span> db.<span class="f">query</span>(<span class="s">"SELECT COUNT(DISTINCT city) AS n FROM users"</span>);
|
||||
<span class="k">await</span> db.<span class="f">query</span>(<span class="s">"SELECT name FROM users ORDER BY age ASC NULLS FIRST"</span>);</pre>
|
||||
|
||||
<h3>完整 SQL 语法支持</h3>
|
||||
<pre><span class="c">// SELECT — 核心查询</span>
|
||||
@@ -730,8 +745,9 @@ db.<span class="f">broadcastChange</span>(<span class="s">'users'</span>);</pre>
|
||||
|
||||
<h2 id="aria-engine">🌲 AriaEngine 自研存储引擎</h2>
|
||||
<p><strong>v0.2.0 新增</strong> — AriaEngine 是专为 MetonaSqlark 设计的页面式存储引擎,对标 SQLite 设计理念。<br>
|
||||
<strong>v0.2.4 生产级</strong> — 二级索引 · MVCC · BloomFilter · WAL CRC全同步 · AES-GCM加密 · Savepoint · EXPLAIN · ANALYZE · REINDEX · VACUUM · BufferPool · 837测试 · 零死代码。<br>
|
||||
<strong>v0.3.2 表达式与并发</strong> — WAL full模式真正同步 · MVCC接入读写路径 · SSTableReader二分查找统一 · crypto实例化 · IndexedDB索引利用 · compactLevel public接口 · WAL大小阈值自动checkpoint · SQL注入防护 · ALTER TABLE · TRUNCATE TABLE · 837测试 44套件。</p>
|
||||
<strong>v0.2.4 生产级</strong> — 二级索引 · MVCC · BloomFilter · WAL CRC全同步 · AES-GCM加密 · Savepoint · EXPLAIN · ANALYZE · REINDEX · VACUUM · BufferPool · 零死代码。<br>
|
||||
<strong>v0.3.2 表达式与并发</strong> — WAL full模式真正同步 · MVCC接入读写路径 · SSTableReader二分查找统一 · crypto实例化 · IndexedDB索引利用 · compactLevel public接口 · WAL大小阈值自动checkpoint · SQL注入防护 · ALTER TABLE · TRUNCATE TABLE · 多标签页同步 · IDB schema持久化。<br>
|
||||
<strong>v0.4.1 Aria 级联与演示页引擎切换</strong> — AriaEngine 外键级联(CASCADE/SET NULL/RESTRICT)· `clearAll()` 重置 API · 演示页 ⚡Memory/🌲Aria 引擎切换器 · 894测试 47套件。</p>
|
||||
|
||||
<h3>存储模式对比</h3>
|
||||
<table>
|
||||
|
||||
+11
-6
@@ -153,7 +153,7 @@
|
||||
<!-- Hero -->
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="badge" style="margin-bottom:24px;"><span class="dot"></span> v0.3.2 表达式与并发 — 837测试 44套件 · 五模式全覆盖 · WAL同步修复 · ALTER/TRUNCATE · SQL注入防护 · 零回归</div>
|
||||
<div class="badge" style="margin-bottom:24px;"><span class="dot"></span> v0.4.1 Aria 级联与演示页引擎切换 — 894测试 47套件 · 流式查询 · 派生表 · 崩溃恢复修复 · 多列哈希连接 · 零回归</div>
|
||||
<h1>前端的 <span class="gradient-text">SQL 数据库</span></h1>
|
||||
<p>TypeScript 原生构建,5 种存储引擎,支持完整 SQL 查询。<br>零运行时依赖,开箱即用。AriaEngine 自研引擎:LSM-Tree + WAL 同步 + MVCC。</p>
|
||||
<div class="actions">
|
||||
@@ -243,8 +243,8 @@ npm install @metona-team/metona-sqlark
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="icon">🌲</div>
|
||||
<h3>AriaEngine <span style="font-size:0.65rem;color:var(--accent);vertical-align:super;">v0.3.2</span></h3>
|
||||
<p>自研 LSM-Tree 页面式存储引擎。MemTable 红黑树 + 多级 SSTable、Bloom Filter 快速判存、WAL full模式真正同步、MVCC 版本链接入读写路径。</p>
|
||||
<h3>AriaEngine <span style="font-size:0.65rem;color:var(--accent);vertical-align:super;">v0.4.1</span></h3>
|
||||
<p>自研 LSM-Tree 页面式存储引擎。MemTable 红黑树 + 多级 SSTable、Bloom Filter 快速判存、WAL full模式真正同步、MVCC 版本链接入读写路径、崩溃恢复 DROP_TABLE 回放修复。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="icon">🔒</div>
|
||||
@@ -296,6 +296,11 @@ npm install @metona-team/metona-sqlark
|
||||
<h3>Query Builder</h3>
|
||||
<p>链式 API + TypeScript 泛型。.select().where().innerJoin().orderBy().limit() — 类型安全,IDE 友好。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="icon">🚰</div>
|
||||
<h3>流式查询 + 派生表</h3>
|
||||
<p>queryStream 逐行回调不物化结果集(大表友好)。FROM (SELECT ...) 派生表、多列哈希连接、COUNT(DISTINCT)、NULLS FIRST/LAST。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -394,12 +399,12 @@ npm install @metona-team/metona-sqlark
|
||||
<p>MetonaSqlark 的核心指标</p>
|
||||
</div>
|
||||
<div class="stats">
|
||||
<div class="stat-card"><div class="num">837</div><div class="label">测试用例</div></div>
|
||||
<div class="stat-card"><div class="num">81.1%</div><div class="label">行覆盖率</div></div>
|
||||
<div class="stat-card"><div class="num">894</div><div class="label">测试用例</div></div>
|
||||
<div class="stat-card"><div class="num">81.5%</div><div class="label">行覆盖率</div></div>
|
||||
<div class="stat-card"><div class="num">~27KB</div><div class="label">gzip 体积</div></div>
|
||||
<div class="stat-card"><div class="num">5</div><div class="label">存储引擎</div></div>
|
||||
<div class="stat-card"><div class="num">36</div><div class="label">SQL 关键字</div></div>
|
||||
<div class="stat-card"><div class="num">44</div><div class="label">测试套件</div></div>
|
||||
<div class="stat-card"><div class="num">46</div><div class="label">测试套件</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user