158 lines
5.0 KiB
TypeScript
158 lines
5.0 KiB
TypeScript
/**
|
|
* 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('支持 DROP TABLE IF EXISTS 语法', () => {
|
|
const ast = parse('DROP TABLE IF EXISTS users');
|
|
expect(ast).toMatchObject({ type: 'DROP_TABLE', name: 'users', ifExists: true });
|
|
});
|
|
|
|
it('DROP TABLE 不带 IF EXISTS', () => {
|
|
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();
|
|
});
|
|
});
|
|
});
|