Source code for benchbox.platforms.clickhouse.adapter

"""Primary adapter for ClickHouse platforms."""

from __future__ import annotations

import logging

from benchbox.platforms.base import DriverIsolationCapability, PlatformAdapter
from benchbox.utils.dependencies import check_platform_dependencies, get_dependency_error_message

from .diagnostics import ClickHouseDiagnosticsMixin
from .metadata import ClickHouseMetadataMixin
from .setup import ClickHouseSetupMixin
from .tuning import ClickHouseTuningMixin
from .workload import ClickHouseWorkloadMixin

logger = logging.getLogger(__name__)


[docs] class ClickHouseAdapter( ClickHouseMetadataMixin, ClickHouseSetupMixin, ClickHouseDiagnosticsMixin, ClickHouseWorkloadMixin, ClickHouseTuningMixin, PlatformAdapter, ): """High-level adapter coordinating ClickHouse operations. Known Limitations: TPC-DS queries with known incompatibilities: - Query 14: INTERSECT DISTINCT requires manual alias addition - Query 30: Query plan cloning not implemented for aggregation steps (Code: 48) - Query 66: Nested aggregation not supported - requires query rewrite - Query 81: Query plan cloning not implemented for aggregation steps (Code: 48) These queries may fail even with transformations applied and require manual query rewriting or ClickHouse engine improvements. """ driver_isolation_capability = DriverIsolationCapability.NOT_FEASIBLE # Known incompatible queries that may fail despite transformations KNOWN_INCOMPATIBLE_QUERIES = { "tpcds": [14, 30, 66, 81], }
[docs] def __init__(self, **config): super().__init__(**config) self._dialect = "clickhouse" # Determine deployment mode (from factory via colon syntax: clickhouse:local). # Default to local mode for easiest onboarding (no credentials required). deployment_mode = config.get("deployment_mode") self.deployment_mode = deployment_mode.lower() if deployment_mode else "local" # Validate deployment mode # Note: "cloud" mode is now a separate first-class platform: clickhouse-cloud # The _is_cloud_subclass flag is set by ClickHouseCloudAdapter to bypass this check valid_modes = {"local", "server"} is_cloud_subclass = config.get("_is_cloud_subclass", False) if self.deployment_mode == "cloud" and not is_cloud_subclass: raise ValueError( "ClickHouse Cloud is now a separate first-class platform.\n" "Use --platform clickhouse-cloud instead of --platform clickhouse:cloud\n" "For more information: benchbox run --platform clickhouse-cloud --help" ) # Cloud mode is valid when called from ClickHouseCloudAdapter if is_cloud_subclass: valid_modes = {"local", "server", "cloud"} if self.deployment_mode not in valid_modes: raise ValueError( f"Invalid ClickHouse deployment mode '{self.deployment_mode}'. " f"Valid modes: {', '.join(sorted(valid_modes))}" ) # Mode-specific validation and setup if self.deployment_mode == "server": available, missing = check_platform_dependencies("clickhouse", ["clickhouse-driver"]) if not available: error_msg = get_dependency_error_message("clickhouse", missing) raise ImportError(error_msg) self._setup_server_mode(config) elif self.deployment_mode == "local": import importlib.util if importlib.util.find_spec("chdb") is None: raise ImportError( "ClickHouse local mode requires chDB but it is not installed.\n" "To resolve this issue:\n" " 1. Install chDB: uv add chdb\n" " 2. Or switch to server mode: --platform clickhouse:server\n" " 3. Or use ClickHouse Cloud: --platform clickhouse-cloud\n" " 4. Or use a different platform (e.g., DuckDB)\n" "\nFor more information about chDB, visit: https://github.com/chdb-io/chdb" ) self._setup_local_mode(config) elif self.deployment_mode == "cloud": # Cloud mode is only valid when called from ClickHouseCloudAdapter # Check for clickhouse-connect dependency import importlib.util if importlib.util.find_spec("clickhouse_connect") is None: raise ImportError( "ClickHouse Cloud requires clickhouse-connect but it is not installed.\n" "To resolve this issue:\n" " 1. Install clickhouse-connect: uv add clickhouse-connect\n" " 2. Or use local mode: --platform clickhouse:local\n" "\nFor more information, visit: https://clickhouse.com/docs/en/integrations/python" ) self._setup_cloud_mode(config)
__all__ = ["ClickHouseAdapter"]