feat(sqlserver): add explicit legacy driver selection

This commit is contained in:
zipg authored and GitHub committed 2026-07-22 23:02:08 +08:00
1 parent 5d1a6e63cd
commit 22ccdef594
8 files changed
+227 -154

No files matched your search

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { isSqlServerLegacyCompatibilityMode, requiresSqlServerLegacyCompatibilityComponent, setSqlServerLegacyCompatibilityMode } from "@/lib/connection/sqlServerLegacyCompatibility";
import { isSqlServerNativeEncryptionDisabled, requiresSqlServerLegacyCompatibilityComponent, setSqlServerLegacyCompatibilityConfig, setSqlServerNativeEncryptionDisabled, sqlServerUsesLegacyCompatibility } from "@/lib/connection/sqlServerLegacyCompatibility";
import type { ConnectionConfig } from "@/types/database";
function connectionConfig(urlParams?: string): ConnectionConfig {
@@ -25,26 +25,51 @@ function connectionConfig(urlParams?: string): ConnectionConfig {
}
describe("SQL Server legacy compatibility", () => {
it("treats existing disabled encryption params as legacy compatibility opt-in", () => {
expect(isSqlServerLegacyCompatibilityMode("sqlserverEncryption=disabled")).toBe(true);
expect(isSqlServerLegacyCompatibilityMode("applicationName=dbx;encrypt=false")).toBe(true);
expect(isSqlServerLegacyCompatibilityMode("?Encrypt=0&applicationName=dbx")).toBe(true);
expect(isSqlServerLegacyCompatibilityMode("encrypt=true")).toBe(false);
it("recognizes native encryption policy independently from the legacy driver profile", () => {
expect(isSqlServerNativeEncryptionDisabled("sqlserverEncryption=disabled")).toBe(true);
expect(isSqlServerNativeEncryptionDisabled("applicationName=dbx;encrypt=false")).toBe(true);
expect(isSqlServerNativeEncryptionDisabled("?Encrypt=0&applicationName=dbx")).toBe(true);
expect(isSqlServerNativeEncryptionDisabled("encrypt=true")).toBe(false);
});
it("updates URL params without keeping conflicting encryption params", () => {
expect(setSqlServerLegacyCompatibilityMode("applicationName=dbx;encrypt=true", true)).toBe("applicationName=dbx&sqlserverEncryption=disabled");
expect(setSqlServerLegacyCompatibilityMode("applicationName=dbx;sqlserverEncryption=disabled", false)).toBe("applicationName=dbx");
it("updates native encryption params without changing the driver profile", () => {
expect(setSqlServerNativeEncryptionDisabled("applicationName=dbx;encrypt=true", true)).toBe("applicationName=dbx&sqlserverEncryption=disabled");
expect(setSqlServerNativeEncryptionDisabled("applicationName=dbx;sqlserverEncryption=disabled", false)).toBe("applicationName=dbx");
});
it("requires the hidden component only for SQL Server legacy compatibility connections", () => {
expect(requiresSqlServerLegacyCompatibilityComponent(connectionConfig("sqlserverEncryption=disabled"))).toBe(true);
expect(requiresSqlServerLegacyCompatibilityComponent(connectionConfig("encrypt=true"))).toBe(false);
it("keeps historical disabled-encryption connections on the native driver", () => {
const config = connectionConfig("sqlserverEncryption=disabled");
expect(sqlServerUsesLegacyCompatibility(config)).toBe(false);
expect(requiresSqlServerLegacyCompatibilityComponent(config)).toBe(false);
expect(
requiresSqlServerLegacyCompatibilityComponent({
...connectionConfig("sqlserverEncryption=disabled"),
...config,
driver_profile: "sqlserver-legacy",
db_type: "mysql",
}),
).toBe(false);
});
it("treats a persisted legacy driver profile as compatibility mode", () => {
const config = connectionConfig("");
config.driver_profile = "sqlserver-legacy";
expect(sqlServerUsesLegacyCompatibility(config)).toBe(true);
expect(requiresSqlServerLegacyCompatibilityComponent(config)).toBe(true);
});
it("updates the explicit driver profile without rewriting native encryption params", () => {
const config = connectionConfig("applicationName=dbx&encrypt=false");
setSqlServerLegacyCompatibilityConfig(config, true);
expect(config.driver_profile).toBe("sqlserver-legacy");
expect(config.driver_label).toBe("SQL Server legacy compatibility component");
expect(config.url_params).toBe("applicationName=dbx&encrypt=false");
setSqlServerLegacyCompatibilityConfig(config, false);
expect(config.driver_profile).toBe("sqlserver");
expect(config.driver_label).toBe("SQL Server");
expect(config.url_params).toBe("applicationName=dbx&encrypt=false");
});
});
@@ -1,34 +1,45 @@
import type { ConnectionConfig } from "@/types/database";
export const SQLSERVER_LEGACY_COMPATIBILITY_DRIVER_KEY = "sqlserver-legacy";
export const SQLSERVER_LEGACY_COMPATIBILITY_DRIVER_LABEL = "SQL Server legacy compatibility component";
export const SQLSERVER_NATIVE_DRIVER_PROFILE = "sqlserver";
export const SQLSERVER_NATIVE_DRIVER_LABEL = "SQL Server";
const SQLSERVER_LEGACY_DISABLED_VALUES = new Set(["disabled", "disable", "false", "0", "off", "no"]);
const SQLSERVER_ENCRYPTION_DISABLED_VALUES = new Set(["disabled", "disable", "false", "0", "off", "no"]);
export function isSqlServerLegacyCompatibilityMode(params: string | undefined): boolean {
export function isSqlServerNativeEncryptionDisabled(params: string | undefined): boolean {
const normalized = (params || "").trim().replace(/^\?/, "").replace(/;/g, "&");
if (!normalized) return false;
const parsed = new URLSearchParams(normalized);
for (const [key, value] of parsed.entries()) {
const normalizedKey = key.trim().toLowerCase();
if (normalizedKey === "sqlserverencryption" || normalizedKey === "encrypt") {
// Accept JDBC-style `encrypt=false` from imported SQL Server URLs as the same opt-in.
if (SQLSERVER_LEGACY_DISABLED_VALUES.has(value.trim().toLowerCase())) return true;
if (SQLSERVER_ENCRYPTION_DISABLED_VALUES.has(value.trim().toLowerCase())) return true;
}
}
return false;
}
export function setSqlServerLegacyCompatibilityMode(params: string | undefined, enabled: boolean): string {
export function setSqlServerNativeEncryptionDisabled(params: string | undefined, disabled: boolean): string {
const normalized = (params || "").trim().replace(/^\?/, "").replace(/;/g, "&");
const parsed = new URLSearchParams(normalized);
for (const key of Array.from(parsed.keys())) {
const normalizedKey = key.trim().toLowerCase();
if (normalizedKey === "sqlserverencryption" || normalizedKey === "encrypt") parsed.delete(key);
}
if (enabled) parsed.set("sqlserverEncryption", "disabled");
if (disabled) parsed.set("sqlserverEncryption", "disabled");
return parsed.toString();
}
export function sqlServerUsesLegacyCompatibility(config: Pick<ConnectionConfig, "db_type" | "driver_profile">): boolean {
return config.db_type === "sqlserver" && config.driver_profile === SQLSERVER_LEGACY_COMPATIBILITY_DRIVER_KEY;
}
export function setSqlServerLegacyCompatibilityConfig(config: Pick<ConnectionConfig, "driver_label" | "driver_profile">, enabled: boolean): void {
config.driver_profile = enabled ? SQLSERVER_LEGACY_COMPATIBILITY_DRIVER_KEY : SQLSERVER_NATIVE_DRIVER_PROFILE;
config.driver_label = enabled ? SQLSERVER_LEGACY_COMPATIBILITY_DRIVER_LABEL : SQLSERVER_NATIVE_DRIVER_LABEL;
}
export function requiresSqlServerLegacyCompatibilityComponent(config: ConnectionConfig): boolean {
return config.db_type === "sqlserver" && isSqlServerLegacyCompatibilityMode(config.url_params);
return sqlServerUsesLegacyCompatibility(config);
}