fix(jdbc): 为缺少依赖的自定义驱动提供安装入口
This commit is contained in:
10 files changed
+68
-6
No files matched your search
@@ -44,7 +44,7 @@ import { prestoSqlBuiltinDriverPaths } from "@/lib/database/prestoSqlBuiltinDriv
|
||||
import { JDBCX_DEFAULT_URL, JDBCX_DRIVER_PROFILE, JDBCX_JDBC_DRIVER_CLASS, ensureJdbcxRuntimeDrivers, isJdbcxRuntimeBundle, isJdbcxRuntimePath, jdbcxHighPrivilegeExtensionsEnabled, setJdbcxHighPrivilegeExtensionsEnabled } from "@/lib/database/jdbcxBuiltinDriver";
|
||||
import { SQLITE_DATABASE_FILE_EXTENSIONS } from "@/lib/database/databaseFileDetection";
|
||||
import { connectionAttemptOriginalErrorMessage, connectionAttemptTimeoutMessage, connectionAttemptTimeoutMs } from "@/lib/connection/connectionAttemptTimeout";
|
||||
import { appendConnectionErrorHints } from "@/lib/connection/connectionErrorHints";
|
||||
import { appendConnectionErrorHints, isJdbcMissingRuntimeDependencyError } from "@/lib/connection/connectionErrorHints";
|
||||
import { postgresTlsModeForForm } from "@/lib/connection/postgresTlsMode";
|
||||
import { normalizeKafkaBootstrapServers } from "@/lib/connection/kafkaBootstrapServers";
|
||||
import { detectMqUiAuthKind, isMqAuthKindAllowedForSystem, type MqUiAuthKind } from "@/lib/connection/mqAuth";
|
||||
@@ -438,6 +438,7 @@ function sshLayersForConfig(config: LegacyConnectionConfig): SshTunnelConfig[] {
|
||||
}
|
||||
|
||||
const form = ref(defaultForm());
|
||||
const showJdbcDependencyDriverManagerAction = computed(() => form.value.db_type === "jdbc" && isJdbcMissingRuntimeDependencyError(connectionErrorDetail.value));
|
||||
|
||||
function externalConfigRecord(value: unknown): Record<string, unknown> {
|
||||
return value && typeof value === "object" && !Array.isArray(value) ? { ...(value as Record<string, unknown>) } : {};
|
||||
@@ -3390,6 +3391,11 @@ async function copyConnectionErrorDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
function openJdbcDriverManagerFromError() {
|
||||
showConnectionErrorDialog.value = false;
|
||||
emit("openDriverStore", { target: "tab", tab: "jdbc" });
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
editingId.value = null;
|
||||
form.value = defaultForm();
|
||||
@@ -6107,6 +6113,10 @@ function openExternalUrl(url: string) {
|
||||
</div>
|
||||
|
||||
<DialogFooter class="gap-2">
|
||||
<Button v-if="showJdbcDependencyDriverManagerAction" variant="outline" @click="openJdbcDriverManagerFromError">
|
||||
<FolderOpen class="mr-1.5 h-3.5 w-3.5" />
|
||||
{{ t("toolbar.driverManager") }}
|
||||
</Button>
|
||||
<Button variant="outline" @click="copyConnectionErrorDetail">
|
||||
<Copy class="mr-1.5 h-3.5 w-3.5" />
|
||||
复制错误
|
||||
|
||||
@@ -522,7 +522,8 @@ export default {
|
||||
jdbcDriverPathsPlaceholder: "/path/to/driver.jar\n/path/to/another-driver.jar",
|
||||
jdbcDriverBrowse: "Choose JDBC driver JAR",
|
||||
jdbcDocs: "View JDBC docs",
|
||||
jdbcPluginHint: "Install the DBX JDBC plugin first, then import the database vendor's JDBC driver JAR.",
|
||||
jdbcPluginHint: "Install the DBX JDBC plugin first. For drivers with external dependencies, install from Maven in Driver Manager or import the driver and all dependency JARs together.",
|
||||
jdbcMissingRuntimeDependencyHint: "This JDBC driver is missing runtime dependencies. Install it from Maven in Driver Manager, or import the driver and all dependency JARs together.",
|
||||
jdbcxExtensions: "JDBCX extensions",
|
||||
jdbcxHighPrivilegeExtensions: "Allow high-privilege extensions",
|
||||
jdbcxHighPrivilegeExtensionsWarning: "Disabled by default. Enabling allows Shell, Script, Web, MCP, and other extensions to execute local commands or access the network.",
|
||||
|
||||
@@ -529,6 +529,7 @@ export default withEnglishFallback({
|
||||
elasticsearchKibanaProxyMode: "proxy de Kibana",
|
||||
elasticsearchKibanaHost: "host de Kibana",
|
||||
elasticsearchKibanaBasePath: "ruta base",
|
||||
jdbcMissingRuntimeDependencyHint: "El controlador JDBC actual carece de dependencias de ejecución. Utilice las coordenadas Maven en 'Administración de controladores' para instalar, o importe el controlador y todos los JAR de dependencia de una vez.",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "Presiona {mod}+Enter para ejecutar",
|
||||
|
||||
@@ -527,6 +527,7 @@ export default withEnglishFallback({
|
||||
elasticsearchKibanaProxyMode: "Proxy Kibana",
|
||||
elasticsearchKibanaHost: "Host Kibana",
|
||||
elasticsearchKibanaBasePath: "Percorso base",
|
||||
jdbcMissingRuntimeDependencyHint: "Il driver JDBC corrente manca di dipendenze runtime. Installare utilizzando le coordinate Maven in 'Gestione driver', o importare il driver e tutti i JAR delle dipendenze in una volta.",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "Premi {mod}+Enter per eseguire",
|
||||
|
||||
@@ -527,6 +527,7 @@ export default withEnglishFallback({
|
||||
elasticsearchKibanaProxyMode: "Kibana プロキシ",
|
||||
elasticsearchKibanaHost: "Kibana ホスト",
|
||||
elasticsearchKibanaBasePath: "ベースパス",
|
||||
jdbcMissingRuntimeDependencyHint: "現在のJDBCドライバーには実行依存関係が不足しています。「ドライバ管理」でMaven座標を使用してインストールするか、ドライバーとすべての依存JARを一度にインポートしてください。",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "{mod}+Enter で実行",
|
||||
|
||||
@@ -528,6 +528,7 @@ export default withEnglishFallback({
|
||||
elasticsearchKibanaProxyMode: "Proxy do Kibana",
|
||||
elasticsearchKibanaHost: "Host do Kibana",
|
||||
elasticsearchKibanaBasePath: "Caminho Base",
|
||||
jdbcMissingRuntimeDependencyHint: "O driver JDBC atual está sem dependências de execução. Por favor, instale-o usando as coordenadas Maven no 'Gerenciamento de Drivers' ou importe o driver e todos os JARs de dependência de uma só vez.",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "Pressione {mod}+Enter para executar",
|
||||
|
||||
@@ -526,7 +526,8 @@ export default withEnglishFallback({
|
||||
jdbcDriverPathsPlaceholder: "/path/to/driver.jar\n/path/to/another-driver.jar",
|
||||
jdbcDriverBrowse: "选择 JDBC 驱动 JAR",
|
||||
jdbcDocs: "查看 JDBC 文档",
|
||||
jdbcPluginHint: "先安装 DBX JDBC 插件,再导入数据库厂商提供的 JDBC 驱动 JAR。",
|
||||
jdbcPluginHint: "先安装 DBX JDBC 插件。有外部依赖的驱动请从驱动管理使用 Maven 安装,或同时导入驱动及全部依赖 JAR。",
|
||||
jdbcMissingRuntimeDependencyHint: "当前 JDBC 驱动缺少运行依赖。请在「驱动管理」中使用 Maven 坐标安装,或一次导入驱动及全部依赖 JAR。",
|
||||
jdbcxExtensions: "JDBCX 扩展",
|
||||
jdbcxHighPrivilegeExtensions: "允许高权限扩展",
|
||||
jdbcxHighPrivilegeExtensionsWarning: "默认禁用。开启后,Shell、Script、Web、MCP 等扩展可以执行本机命令或访问网络。",
|
||||
|
||||
@@ -528,6 +528,7 @@ export default withEnglishFallback({
|
||||
elasticsearchKibanaProxyMode: "Kibana 代理",
|
||||
elasticsearchKibanaHost: "Kibana 主機",
|
||||
elasticsearchKibanaBasePath: "基礎路徑",
|
||||
jdbcMissingRuntimeDependencyHint: "目前 JDBC 驅動缺少執行依賴。請在「驅動管理」中使用 Maven 座標安裝,或一次匯入驅動及全部依賴 JAR。",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "按 {mod}+Enter 執行查詢",
|
||||
|
||||
@@ -17,7 +17,25 @@ function mysqlConfig(urlParams: string | undefined): ConnectionConfig {
|
||||
};
|
||||
}
|
||||
|
||||
const t = (key: string) => (key === "connection.mysqlTlsConnectionFailureHint" ? "Set TLS Mode to Disabled." : key);
|
||||
function jdbcConfig(): ConnectionConfig {
|
||||
return {
|
||||
id: "jdbc-test",
|
||||
name: "TDengine JDBC",
|
||||
db_type: "jdbc",
|
||||
host: "127.0.0.1",
|
||||
port: 6041,
|
||||
username: "root",
|
||||
password: "",
|
||||
database: "dbx_tdengine_demo",
|
||||
ssl: false,
|
||||
};
|
||||
}
|
||||
|
||||
const t = (key: string) => {
|
||||
if (key === "connection.mysqlTlsConnectionFailureHint") return "Set TLS Mode to Disabled.";
|
||||
if (key === "connection.jdbcMissingRuntimeDependencyHint") return "Install from Maven or import every dependency JAR.";
|
||||
return key;
|
||||
};
|
||||
|
||||
describe("appendConnectionErrorHints", () => {
|
||||
it("adds a MySQL TLS hint for non-disabled TLS failures", () => {
|
||||
@@ -45,4 +63,18 @@ describe("appendConnectionErrorHints", () => {
|
||||
|
||||
expect(message).toBe("Access denied for user root");
|
||||
});
|
||||
|
||||
it("adds an installation hint when a custom JDBC driver is missing a runtime dependency", () => {
|
||||
const error = "Missing Java class com.alibaba.fastjson.JSONException. Install the required runtime dependency.";
|
||||
const message = appendConnectionErrorHints(jdbcConfig(), error, t);
|
||||
|
||||
expect(message).toContain(error);
|
||||
expect(message).toContain("Install from Maven or import every dependency JAR.");
|
||||
});
|
||||
|
||||
it("does not add the JDBC dependency hint to non-JDBC connections", () => {
|
||||
const error = "Missing Java class com.alibaba.fastjson.JSONException. Install the required runtime dependency.";
|
||||
|
||||
expect(appendConnectionErrorHints(mysqlConfig(undefined), error, t)).toBe(error);
|
||||
});
|
||||
});
|
||||
@@ -37,10 +37,23 @@ function isMysqlTlsLikeFailure(message: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
export function isJdbcMissingRuntimeDependencyError(message: string): boolean {
|
||||
return /Missing Java class|NoClassDefFoundError|ClassNotFoundException/i.test(message);
|
||||
}
|
||||
|
||||
function appendHint(message: string, hint: string): string {
|
||||
return message.includes(hint) ? message : `${message}\n\n${hint}`;
|
||||
}
|
||||
|
||||
export function appendConnectionErrorHints(config: ConnectionConfig | undefined, message: string, t: Translate): string {
|
||||
if (!config || config.db_type !== "mysql") return message;
|
||||
if (!config) return message;
|
||||
let result = message;
|
||||
if (config.db_type === "jdbc" && isJdbcMissingRuntimeDependencyError(message)) {
|
||||
result = appendHint(result, t("connection.jdbcMissingRuntimeDependencyHint"));
|
||||
}
|
||||
if (config.db_type !== "mysql") return result;
|
||||
if (mysqlTlsMode(config) === "disabled") return message;
|
||||
if (!isMysqlTlsLikeFailure(message)) return message;
|
||||
const hint = t("connection.mysqlTlsConnectionFailureHint");
|
||||
return message.includes(hint) ? message : `${message}\n\n${hint}`;
|
||||
return appendHint(message, hint);
|
||||
}
|
||||
Reference in new issue
Block a user