mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-19 11:51:50 +08:00
🐛 fix(sqlserver): 修复对象 SQL 定义获取失败
- SQL Server 对象定义改为通过 sys.all_sql_modules 按库、schema、对象名精确查询 - 增加 sp_helptext 兼容候选,支持拼接多行 Text 返回完整定义 - 统一修复视图、函数/存储过程、触发器定义查看与对象修改入口 - 补充 SQL Server 对象定义查询和组件回归测试
This commit is contained in:
81
frontend/src/utils/sqlServerObjectDefinition.ts
Normal file
81
frontend/src/utils/sqlServerObjectDefinition.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
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];
|
||||
};
|
||||
Reference in New Issue
Block a user