mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-18 11:22:08 +08:00
- SQL Server 对象定义改为通过 sys.all_sql_modules 按库、schema、对象名精确查询 - 增加 sp_helptext 兼容候选,支持拼接多行 Text 返回完整定义 - 统一修复视图、函数/存储过程、触发器定义查看与对象修改入口 - 补充 SQL Server 对象定义查询和组件回归测试
82 lines
3.3 KiB
TypeScript
82 lines
3.3 KiB
TypeScript
import { splitQualifiedNameSegments } from './qualifiedName';
|
|
|
|
export type SqlServerObjectDefinitionKind = 'view' | 'routine' | 'trigger';
|
|
|
|
const SQL_SERVER_OBJECT_TYPES: Record<SqlServerObjectDefinitionKind, string[]> = {
|
|
view: ['V'],
|
|
routine: ['P', 'PC', 'RF', 'FN', 'FS', 'FT', 'IF', 'TF'],
|
|
trigger: ['TR', 'TA'],
|
|
};
|
|
|
|
const escapeSqlServerLiteral = (raw: string): string => String(raw || '').replace(/'/g, "''");
|
|
|
|
const quoteSqlServerIdentifier = (raw: string): string => `[${String(raw || '').replace(/]/g, ']]')}]`;
|
|
|
|
const buildSqlServerObjectRef = (schemaName: string, objectName: string): string => {
|
|
const object = String(objectName || '').trim();
|
|
const schema = String(schemaName || '').trim();
|
|
if (!object) return '';
|
|
if (!schema) return object;
|
|
return `${quoteSqlServerIdentifier(schema)}.${quoteSqlServerIdentifier(object)}`;
|
|
};
|
|
|
|
const resolveSqlServerObjectTarget = (rawObjectName: string, fallbackDbName: string) => {
|
|
const segments = splitQualifiedNameSegments(rawObjectName).filter(Boolean);
|
|
const objectName = String(segments[segments.length - 1] || '').trim();
|
|
let schemaName = '';
|
|
let databaseName = String(fallbackDbName || '').trim();
|
|
|
|
if (segments.length >= 3) {
|
|
databaseName = String(segments[segments.length - 3] || databaseName).trim();
|
|
schemaName = String(segments[segments.length - 2] || '').trim();
|
|
} else if (segments.length === 2) {
|
|
schemaName = String(segments[0] || '').trim();
|
|
}
|
|
|
|
return { databaseName, schemaName, objectName };
|
|
};
|
|
|
|
export const buildSqlServerObjectDefinitionQueries = (
|
|
kind: SqlServerObjectDefinitionKind,
|
|
objectName: string,
|
|
dbName: string,
|
|
resultAlias: string,
|
|
): string[] => {
|
|
const target = resolveSqlServerObjectTarget(objectName, dbName);
|
|
if (!target.objectName) return [];
|
|
|
|
const catalogPrefix = target.databaseName ? `${quoteSqlServerIdentifier(target.databaseName)}.` : '';
|
|
const safeObjectName = escapeSqlServerLiteral(target.objectName);
|
|
const safeSchemaName = escapeSqlServerLiteral(target.schemaName);
|
|
const objectTypes = SQL_SERVER_OBJECT_TYPES[kind] || [];
|
|
const typeFilter = objectTypes.length > 0
|
|
? ` AND o.type IN (${objectTypes.map((type) => `'${type}'`).join(', ')})\n`
|
|
: '';
|
|
const schemaFilter = target.schemaName
|
|
? ` AND s.name = N'${safeSchemaName}'\n`
|
|
: '';
|
|
const schemaOrder = target.schemaName
|
|
? 's.name'
|
|
: "CASE WHEN s.name = N'dbo' THEN 0 WHEN s.name = N'sys' THEN 1 ELSE 2 END, s.name";
|
|
|
|
const moduleQuery = [
|
|
`SELECT TOP (1)`,
|
|
` m.definition AS ${resultAlias}`,
|
|
`FROM ${catalogPrefix}sys.all_sql_modules AS m`,
|
|
`JOIN ${catalogPrefix}sys.all_objects AS o ON o.object_id = m.object_id`,
|
|
`JOIN ${catalogPrefix}sys.schemas AS s ON s.schema_id = o.schema_id`,
|
|
`WHERE o.name = N'${safeObjectName}'`,
|
|
typeFilter.trimEnd(),
|
|
schemaFilter.trimEnd(),
|
|
` AND m.definition IS NOT NULL`,
|
|
`ORDER BY ${schemaOrder}, o.name`,
|
|
].filter(Boolean).join('\n');
|
|
|
|
const objectRef = buildSqlServerObjectRef(target.schemaName, target.objectName);
|
|
const helpTextProcedure = target.databaseName
|
|
? `EXEC ${quoteSqlServerIdentifier(target.databaseName)}.sys.sp_helptext @objname = N'${escapeSqlServerLiteral(objectRef)}'`
|
|
: `EXEC sys.sp_helptext @objname = N'${escapeSqlServerLiteral(objectRef)}'`;
|
|
|
|
return [moduleQuery, helpTextProcedure];
|
|
};
|