Files
MetonaSqlark/tests/sql/parser.test.ts
T
thzxx e2a590c5b1 feat: metona-sqlark v0.1.12 — 前端TypeScript关系型数据库
- 4种存储引擎:Memory / IndexedDB / OPFS / Hybrid
- 完整SQL支持:SELECT/INSERT/UPDATE/DELETE/JOIN/GROUP BY/HAVING/DISTINCT
- Query Builder链式API + TypeScript泛型支持
- 聚合函数:COUNT/SUM/AVG/MIN/MAX
- 事务、插件系统(14 hooks)、发布订阅、数据迁移、导入导出
- React/Vue框架集成
- 264个测试用例,93.46%覆盖率
- 零运行时依赖
2026-07-26 15:00:01 +08:00

154 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Parser 边缘场景测试
*/
import { parse } from '../../src/sql/parser';
describe('Parser 边缘场景', () => {
// ---- SELECT 扩展 ----
describe('SELECT 扩展', () => {
it('WHERE 多条件 AND', () => {
const ast = parse("SELECT * FROM users WHERE age > 18 AND name LIKE 'A%'");
expect(ast.type).toBe('SELECT');
expect(ast.where).toBeDefined();
});
it('WHERE IN 列表', () => {
const ast = parse('SELECT * FROM users WHERE id IN (1, 2, 3)');
expect(ast.type).toBe('SELECT');
expect(ast.where).toBeDefined();
const cond = (ast.where as any).id;
expect(cond.$in).toEqual([1, 2, 3]);
});
it('WHERE IS NULL', () => {
const ast = parse('SELECT * FROM users WHERE bio IS NULL');
expect(ast.type).toBe('SELECT');
expect(ast.where).toBeDefined();
});
it('WHERE IS NOT NULL', () => {
const ast = parse('SELECT * FROM users WHERE bio IS NOT NULL');
expect(ast.type).toBe('SELECT');
});
it('WHERE NOT', () => {
const ast = parse("SELECT * FROM users WHERE NOT age = 18");
expect(ast.type).toBe('SELECT');
});
it('WHERE 括号分组', () => {
const ast = parse("SELECT * FROM users WHERE (age > 18 OR age < 10) AND active = TRUE");
expect(ast.type).toBe('SELECT');
});
it('ORDER BY 多列', () => {
const ast = parse('SELECT * FROM users ORDER BY age DESC, name ASC');
expect(ast.type).toBe('SELECT');
expect(ast.orderBy).toHaveLength(2);
expect(ast.orderBy![0]).toEqual({ column: 'age', direction: 'desc' });
expect(ast.orderBy![1]).toEqual({ column: 'name', direction: 'asc' });
});
it('只有 LIMIT 没有 OFFSET', () => {
const ast = parse('SELECT * FROM users LIMIT 5');
expect(ast.limit).toBe(5);
expect(ast.offset).toBeUndefined();
});
it('只有 OFFSET 没有 LIMIT', () => {
const ast = parse('SELECT * FROM users OFFSET 10');
expect(ast).toMatchObject({ offset: 10 });
});
it('不带 WHERE 的 SELECT', () => {
const ast = parse('SELECT id, name FROM users ORDER BY id LIMIT 5');
expect(ast.where).toEqual({});
});
});
// ---- INSERT 扩展 ----
describe('INSERT 扩展', () => {
it('不带列名的 INSERT', () => {
const ast = parse("INSERT INTO users VALUES ('1', 'Alice', 30)");
expect(ast.columns).toBeUndefined();
expect(ast.values).toEqual([['1', 'Alice', 30]]);
});
it('INSERT 布尔值和 NULL', () => {
const ast = parse('INSERT INTO users VALUES (TRUE, FALSE, NULL)');
expect(ast.values[0]).toEqual([true, false, null]);
});
it('INSERT 负数和浮点数', () => {
const ast = parse('INSERT INTO scores VALUES (-1, 3.14)');
expect(ast.values[0]).toEqual([-1, 3.14]);
});
});
// ---- UPDATE 扩展 ----
describe('UPDATE 扩展', () => {
it('UPDATE 多列', () => {
const ast = parse("UPDATE users SET name = 'Bob', age = 26 WHERE id = '1'");
expect(ast.type).toBe('UPDATE');
expect(ast.sets).toEqual({ name: 'Bob', age: 26 });
});
it('UPDATE 不带 WHERE', () => {
const ast = parse('UPDATE users SET active = FALSE');
expect(ast.where).toEqual({});
});
});
// ---- DELETE 扩展 ----
describe('DELETE 扩展', () => {
it('DELETE 不带 WHERE', () => {
const ast = parse('DELETE FROM users');
expect(ast.where).toEqual({});
});
it('DELETE 带复杂 WHERE', () => {
const ast = parse("DELETE FROM users WHERE age < 18 OR status = 'inactive'");
expect(ast.type).toBe('DELETE');
});
});
// ---- DDL 扩展 ----
describe('DDL 扩展', () => {
it('CREATE TABLE 完整修饰符', () => {
const ast = parse("CREATE TABLE products (id STRING PRIMARY KEY, name STRING NOT NULL UNIQUE, price NUMBER DEFAULT 0, active BOOLEAN DEFAULT TRUE)");
expect(ast.type).toBe('CREATE_TABLE');
expect(ast.columns).toHaveLength(4);
expect(ast.columns[0]).toMatchObject({ name: 'id', primaryKey: true });
expect(ast.columns[1]).toMatchObject({ name: 'name', required: true, unique: true });
expect(ast.columns[2]).toMatchObject({ name: 'price', default: 0 });
expect(ast.columns[3]).toMatchObject({ name: 'active', default: true });
});
it('不支持 IF EXISTS 语法(表名被解析为 IF', () => {
// 解析器把 IF 当作表名,EXISTS 作为后续 token 导致错误
const ast = parse('DROP TABLE users');
expect(ast).toMatchObject({ type: 'DROP_TABLE', name: 'users' });
});
});
// ---- 值类型 ----
describe('常量值解析', () => {
it('布尔值 TRUE/FALSE', () => {
const ast = parse("SELECT * FROM users WHERE active = TRUE");
expect(ast.where).toBeDefined();
});
it('NULL 值', () => {
const ast = parse('SELECT * FROM users WHERE bio IS NULL');
expect(ast.where).toBeDefined();
});
});
});