From 6743b676050ce939936cd842412eeb811f57bf85 Mon Sep 17 00:00:00 2001 From: busya Date: Fri, 29 May 2026 14:32:00 +0300 Subject: [PATCH] fix(translate): normalize backend dialect detection with explicit mapping - Replace fragile substring check (any(kw in backend for kw in ('clickhouse', 'ch'))) with a proper _backend_normalize mapping + exact comparison. Fixes misdetection of Greenplum (postgresql) and other backends. - Add 'clickhousedb' to CLICKHOUSE_DIALECTS so SQL generator uses backtick quoting and correct INSERT strategy for ClickHouse. - Normalize _extract_dialect to map 'clickhousedb' -> 'clickhouse' and 'greenplum' -> 'postgresql'. --- .../translate/service_target_schema.py | 25 ++++++++++++++++++- .../src/plugins/translate/service_utils.py | 18 ++++++++++--- .../src/plugins/translate/sql_generator.py | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/backend/src/plugins/translate/service_target_schema.py b/backend/src/plugins/translate/service_target_schema.py index bb3c9cc2..ef8f5d22 100644 --- a/backend/src/plugins/translate/service_target_schema.py +++ b/backend/src/plugins/translate/service_target_schema.py @@ -241,8 +241,31 @@ def validate_target_table_schema( safe_schema = (req.target_schema or "public").replace("'", "''") safe_table = req.target_table.replace("'", "''") + # Нормализуем backend через маппинг (как в get_dialect_from_database) + # чтобы правильно обработать "clickhousedb" → "clickhouse", + # "greenplum" → "postgresql" и другие варианты + _backend_normalize = { + "clickhouse": "clickhouse", + "clickhousedb": "clickhouse", + "postgresql": "postgresql", + "greenplum": "postgresql", + "mysql": "mysql", + "mssql": "mssql", + "sqlite": "sqlite", + "oracle": "oracle", + "snowflake": "snowflake", + "bigquery": "bigquery", + "redshift": "redshift", + "presto": "presto", + "trino": "trino", + "druid": "druid", + "hive": "hive", + "spark": "spark", + "databricks": "databricks", + } + normalized_backend = _backend_normalize.get(backend.lower().strip(), backend.lower().strip()) # ClickHouse использует system.columns, всё остальное — information_schema.columns - is_clickhouse = any(kw in backend.lower() for kw in ("clickhouse", "ch")) + is_clickhouse = normalized_backend == "clickhouse" if is_clickhouse: sql = ( f"SELECT name, type, default_expression AS data_default " diff --git a/backend/src/plugins/translate/service_utils.py b/backend/src/plugins/translate/service_utils.py index a26972d7..428f14ec 100644 --- a/backend/src/plugins/translate/service_utils.py +++ b/backend/src/plugins/translate/service_utils.py @@ -7,15 +7,27 @@ from ...schemas.translate import TranslateJobResponse # #region _extract_dialect [TYPE Function] -# @BRIEF Extract database dialect from Superset backend URI. +# @BRIEF Extract database dialect from Superset backend URI or engine name. def _extract_dialect(backend: str) -> str: - """Extract dialect name from a Superset database backend URI.""" + """Extract dialect name from a Superset database backend URI or engine name. + + Handles both URI formats (e.g. 'postgresql://...', 'clickhousedb://...') + and plain engine names (e.g. 'postgresql', 'clickhousedb') returned by Superset. + Normalises known variants like 'clickhousedb' → 'clickhouse'. + """ if not backend: return "unknown" try: + # Extract scheme from URI or use plain name scheme = backend.split("://")[0] dialect = scheme.split("+")[0] - return dialect.lower() + raw = dialect.lower() + # Normalise known Superset backend variants + dialect_map = { + "clickhousedb": "clickhouse", + "greenplum": "postgresql", + } + return dialect_map.get(raw, raw) except Exception: return "unknown" # #endregion _extract_dialect diff --git a/backend/src/plugins/translate/sql_generator.py b/backend/src/plugins/translate/sql_generator.py index 20e30378..618bad91 100644 --- a/backend/src/plugins/translate/sql_generator.py +++ b/backend/src/plugins/translate/sql_generator.py @@ -18,7 +18,7 @@ from ...core.logger import belief_scope, logger # PostgreSQL/Greenplum dialects that support ON CONFLICT POSTGRESQL_DIALECTS = {"postgresql", "redshift", "greenplum"} # Dialects that use backtick or no quoting -CLICKHOUSE_DIALECTS = {"clickhouse"} +CLICKHOUSE_DIALECTS = {"clickhouse", "clickhousedb"} # #region _normalize_timestamp_value [C:2] [TYPE Function] [SEMANTICS translate,sql,timestamp]