mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-06 06:13:51 +08:00
Merge pull request #451 from TonyJiangWJ/feature/sql-snippets
# Conflicts: # frontend/package.json.md5
This commit is contained in:
73
frontend/src/utils/sqlSnippetDefaults.test.ts
Normal file
73
frontend/src/utils/sqlSnippetDefaults.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { DEFAULT_SQL_SNIPPETS, BUILTIN_SNIPPET_MAP } from './sqlSnippetDefaults';
|
||||
import type { SqlSnippet } from '../types';
|
||||
|
||||
describe('sqlSnippetDefaults', () => {
|
||||
it('DEFAULT_SQL_SNIPPETS should be a non-empty array', () => {
|
||||
expect(Array.isArray(DEFAULT_SQL_SNIPPETS)).toBe(true);
|
||||
expect(DEFAULT_SQL_SNIPPETS.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('every default snippet should have required fields', () => {
|
||||
for (const s of DEFAULT_SQL_SNIPPETS) {
|
||||
expect(s.id).toBeTruthy();
|
||||
expect(s.prefix).toBeTruthy();
|
||||
expect(s.name).toBeTruthy();
|
||||
expect(s.body).toBeTruthy();
|
||||
expect(s.isBuiltin).toBe(true);
|
||||
expect(typeof s.createdAt).toBe('number');
|
||||
}
|
||||
});
|
||||
|
||||
it('every prefix should be lowercase alphanumeric/underscore', () => {
|
||||
for (const s of DEFAULT_SQL_SNIPPETS) {
|
||||
expect(s.prefix).toMatch(/^[a-z0-9_]+$/);
|
||||
}
|
||||
});
|
||||
|
||||
it('prefixes should be unique', () => {
|
||||
const prefixes = DEFAULT_SQL_SNIPPETS.map((s) => s.prefix);
|
||||
expect(new Set(prefixes).size).toBe(prefixes.length);
|
||||
});
|
||||
|
||||
it('ids should be unique', () => {
|
||||
const ids = DEFAULT_SQL_SNIPPETS.map((s) => s.id);
|
||||
expect(new Set(ids).size).toBe(ids.length);
|
||||
});
|
||||
|
||||
it('all default snippets should have snippet syntax in body', () => {
|
||||
for (const s of DEFAULT_SQL_SNIPPETS) {
|
||||
const hasTabStopOrVariable = /\$\d|\$\{|CURRENT_/.test(s.body);
|
||||
expect(hasTabStopOrVariable).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('time-variable snippets should contain CURRENT_ markers', () => {
|
||||
const seld = DEFAULT_SQL_SNIPPETS.find((s) => s.prefix === 'seld');
|
||||
expect(seld).toBeDefined();
|
||||
expect(seld!.body).toContain('CURRENT_YEAR');
|
||||
expect(seld!.body).toContain('CURRENT_MONTH');
|
||||
expect(seld!.body).toContain('CURRENT_DATE');
|
||||
|
||||
const inst = DEFAULT_SQL_SNIPPETS.find((s) => s.prefix === 'inst');
|
||||
expect(inst).toBeDefined();
|
||||
expect(inst!.body).toContain('CURRENT_HOUR');
|
||||
expect(inst!.body).toContain('CURRENT_MINUTE');
|
||||
expect(inst!.body).toContain('CURRENT_SECOND');
|
||||
});
|
||||
|
||||
it('BUILTIN_SNIPPET_MAP should contain all default snippet ids', () => {
|
||||
for (const s of DEFAULT_SQL_SNIPPETS) {
|
||||
expect(BUILTIN_SNIPPET_MAP[s.id]).toBeDefined();
|
||||
expect(BUILTIN_SNIPPET_MAP[s.id].prefix).toBe(s.prefix);
|
||||
expect(BUILTIN_SNIPPET_MAP[s.id].body).toBe(s.body);
|
||||
}
|
||||
});
|
||||
|
||||
it('BUILTIN_SNIPPET_MAP entries should be independent copies', () => {
|
||||
for (const s of DEFAULT_SQL_SNIPPETS) {
|
||||
const mapped = BUILTIN_SNIPPET_MAP[s.id];
|
||||
expect(mapped).not.toBe(s);
|
||||
}
|
||||
});
|
||||
});
|
||||
154
frontend/src/utils/sqlSnippetDefaults.ts
Normal file
154
frontend/src/utils/sqlSnippetDefaults.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import type { SqlSnippet } from "../types";
|
||||
|
||||
const builtinSnippets: Omit<SqlSnippet, "createdAt">[] = [
|
||||
{
|
||||
id: "builtin-sel",
|
||||
prefix: "sel",
|
||||
name: "SELECT 基本查询",
|
||||
description: "基本 SELECT 查询模板",
|
||||
body: "SELECT ${1:column_list} FROM ${2:table_name}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-selw",
|
||||
prefix: "selw",
|
||||
name: "SELECT WHERE",
|
||||
description: "带 WHERE 条件的 SELECT 查询",
|
||||
body: "SELECT ${1:columns} FROM ${2:table_name} WHERE ${3:condition}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-selj",
|
||||
prefix: "selj",
|
||||
name: "SELECT JOIN",
|
||||
description: "带 INNER JOIN 的 SELECT 查询",
|
||||
body: "SELECT ${1:columns}\nFROM ${2:t1}\nINNER JOIN ${3:t2} ON ${4:t1.id} = ${5:t2.id}\nWHERE ${6:condition}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-ins",
|
||||
prefix: "ins",
|
||||
name: "INSERT",
|
||||
description: "INSERT 插入数据模板",
|
||||
body: "INSERT INTO ${1:table_name} (${2:columns})\nVALUES (${3:values})$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-upd",
|
||||
prefix: "upd",
|
||||
name: "UPDATE",
|
||||
description: "UPDATE 更新数据模板",
|
||||
body: "UPDATE ${1:table_name}\nSET ${2:column} = ${3:value}\nWHERE ${4:condition}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-del",
|
||||
prefix: "del",
|
||||
name: "DELETE",
|
||||
description: "DELETE 删除数据模板",
|
||||
body: "DELETE FROM ${1:table_name}\nWHERE ${2:condition}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-ct",
|
||||
prefix: "ct",
|
||||
name: "CREATE TABLE",
|
||||
description: "CREATE TABLE 建表模板",
|
||||
body: "CREATE TABLE ${1:table_name} (\n ${2:id} INT PRIMARY KEY AUTO_INCREMENT,\n ${3:col} ${4:VARCHAR(255)} NOT NULL\n)$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-alt",
|
||||
prefix: "alt",
|
||||
name: "ALTER TABLE",
|
||||
description: "ALTER TABLE 添加列模板",
|
||||
body: "ALTER TABLE ${1:table_name}\nADD COLUMN ${2:col} ${3:VARCHAR(255)}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-dro",
|
||||
prefix: "dro",
|
||||
name: "DROP TABLE",
|
||||
description: "DROP TABLE 删表模板",
|
||||
body: "DROP TABLE IF EXISTS ${1:table_name}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-grp",
|
||||
prefix: "grp",
|
||||
name: "GROUP BY",
|
||||
description: "带 GROUP BY 的聚合查询模板",
|
||||
body: "SELECT ${1:col}, COUNT(*)\nFROM ${2:table_name}\nGROUP BY ${1:col}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-ljo",
|
||||
prefix: "ljo",
|
||||
name: "LEFT JOIN",
|
||||
description: "LEFT JOIN 左连接模板",
|
||||
body: "LEFT JOIN ${1:t} ON ${2:left.col} = ${3:right.col}$0",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-sub",
|
||||
prefix: "sub",
|
||||
name: "子查询",
|
||||
description: "IN 子查询模板",
|
||||
body: "SELECT ${1:cols}\nFROM ${2:t1}\nWHERE ${3:col} IN (\n SELECT ${4:col} FROM ${5:t2} WHERE ${6:cond}\n)$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-lim",
|
||||
prefix: "lim",
|
||||
name: "LIMIT 查询",
|
||||
description: "带 LIMIT 的分页查询模板",
|
||||
body: "SELECT ${1:cols} FROM ${2:table_name} LIMIT ${3:10}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-ord",
|
||||
prefix: "ord",
|
||||
name: "ORDER BY",
|
||||
description: "带排序的查询模板",
|
||||
body: "SELECT ${1:cols} FROM ${2:table_name} ORDER BY ${3:col} ${4|ASC,DESC|}$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-seld",
|
||||
prefix: "seld",
|
||||
name: "SELECT 按日期查询",
|
||||
description: "按日期条件过滤的 SELECT 查询,自动填入当天日期",
|
||||
body: "SELECT ${1:cols} FROM ${2:table_name}\nWHERE ${3:date_col} >= '${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}'$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-ctt",
|
||||
prefix: "ctt",
|
||||
name: "CREATE TABLE(含时间列)",
|
||||
description: "建表模板,含 created_at / updated_at 时间列",
|
||||
body: "CREATE TABLE ${1:table_name} (\n ${2:id} INT PRIMARY KEY AUTO_INCREMENT,\n ${3:col} ${4:VARCHAR(255)},\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n)$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
{
|
||||
id: "builtin-inst",
|
||||
prefix: "inst",
|
||||
name: "INSERT(含时间戳)",
|
||||
description: "INSERT 模板,自动填入当前时间戳",
|
||||
body: "INSERT INTO ${1:table_name} (${2:columns}, created_at)\nVALUES (${3:values}, '${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}')$0;",
|
||||
isBuiltin: true,
|
||||
},
|
||||
];
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
export const DEFAULT_SQL_SNIPPETS: SqlSnippet[] = builtinSnippets.map(
|
||||
(s, i) => ({
|
||||
...s,
|
||||
createdAt: now + i,
|
||||
})
|
||||
);
|
||||
|
||||
export const BUILTIN_SNIPPET_MAP: Record<string, SqlSnippet> = {};
|
||||
for (const s of DEFAULT_SQL_SNIPPETS) {
|
||||
BUILTIN_SNIPPET_MAP[s.id] = { ...s };
|
||||
}
|
||||
Reference in New Issue
Block a user