feat: 打通出库作业链路
This commit is contained in:
86
tools/mcp/sqlserver-mcp-server/dist/sql.js
vendored
Normal file
86
tools/mcp/sqlserver-mcp-server/dist/sql.js
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
export function quoteIdentifier(identifier) {
|
||||
const trimmed = identifier.trim();
|
||||
if (!trimmed) {
|
||||
throw new Error("SQL identifier must not be empty.");
|
||||
}
|
||||
return `[${trimmed.replaceAll("]", "]]")}]`;
|
||||
}
|
||||
export function qualifyName(schemaName, objectName) {
|
||||
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(objectName)}`;
|
||||
}
|
||||
export function assertSafeSelect(query) {
|
||||
const trimmed = query.trim();
|
||||
if (!trimmed) {
|
||||
throw new Error("SELECT query must not be empty.");
|
||||
}
|
||||
const withoutTrailingSemicolon = trimmed.replace(/;+\s*$/u, "");
|
||||
if (withoutTrailingSemicolon.includes(";")) {
|
||||
throw new Error("Only a single SELECT statement is allowed.");
|
||||
}
|
||||
if (!/^(select|with)\b/iu.test(withoutTrailingSemicolon)) {
|
||||
throw new Error("Only SELECT queries or CTE queries starting with WITH are allowed.");
|
||||
}
|
||||
if (/\b(insert|update|delete|merge|drop|alter|create|truncate|exec|execute|grant|revoke)\b/iu.test(withoutTrailingSemicolon)) {
|
||||
throw new Error("SELECT query contains a disallowed mutating keyword.");
|
||||
}
|
||||
}
|
||||
export function buildWhereClause(criteria, prefix) {
|
||||
const entries = Object.entries(criteria).filter(([, value]) => value !== undefined);
|
||||
if (entries.length === 0) {
|
||||
throw new Error("WHERE criteria must include at least one field.");
|
||||
}
|
||||
const params = [];
|
||||
const parts = entries.map(([key, value], index) => {
|
||||
const column = quoteIdentifier(key);
|
||||
if (value === null) {
|
||||
return `${column} IS NULL`;
|
||||
}
|
||||
const name = `${prefix}${index}`;
|
||||
params.push({ name, value });
|
||||
return `${column} = @${name}`;
|
||||
});
|
||||
return {
|
||||
clause: parts.join(" AND "),
|
||||
params
|
||||
};
|
||||
}
|
||||
export function resolveDatabaseName(requested, defaultDatabase, allowedDatabases) {
|
||||
const databaseName = (requested?.trim() || defaultDatabase.trim());
|
||||
if (!databaseName) {
|
||||
throw new Error("Database name is required.");
|
||||
}
|
||||
if (allowedDatabases.length === 0) {
|
||||
return databaseName;
|
||||
}
|
||||
const match = allowedDatabases.find((allowed) => allowed.toLowerCase() === databaseName.toLowerCase());
|
||||
if (!match) {
|
||||
throw new Error(`Database '${databaseName}' is not in the configured allowed database list.`);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
export function validateProcedureDefinition(definition, schemaName, procedureName) {
|
||||
const trimmed = definition.trim();
|
||||
if (!/^(create\s+(or\s+alter\s+)?|alter\s+)proc(edure)?\b/iu.test(trimmed)) {
|
||||
throw new Error("Stored procedure definition must start with CREATE PROCEDURE, ALTER PROCEDURE, or CREATE OR ALTER PROCEDURE.");
|
||||
}
|
||||
const nameMatch = trimmed.match(/^(?:create\s+(?:or\s+alter\s+)?|alter\s+)proc(?:edure)?\s+([^\s(@;]+)/iu);
|
||||
if (!nameMatch) {
|
||||
throw new Error("Stored procedure definition must include a procedure name.");
|
||||
}
|
||||
const normalizedExpected = normalizeObjectName(`${schemaName}.${procedureName}`);
|
||||
const normalizedActual = normalizeObjectName(nameMatch[1]);
|
||||
if (normalizedActual !== normalizedExpected) {
|
||||
throw new Error(`Stored procedure definition name '${nameMatch[1]}' does not match requested name '${schemaName}.${procedureName}'.`);
|
||||
}
|
||||
}
|
||||
function normalizeObjectName(name) {
|
||||
return name
|
||||
.replaceAll("[", "")
|
||||
.replaceAll("]", "")
|
||||
.replaceAll("\"", "")
|
||||
.split(".")
|
||||
.map((part) => part.trim().toLowerCase())
|
||||
.filter(Boolean)
|
||||
.join(".");
|
||||
}
|
||||
//# sourceMappingURL=sql.js.map
|
||||
Reference in New Issue
Block a user