mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
fix(clickhouse): add clickhouse connect driver (#23185)
This commit is contained in:
@@ -16,12 +16,26 @@
|
||||
# under the License.
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from typing import Any, Dict, Optional, Type
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.types import (
|
||||
Boolean,
|
||||
Date,
|
||||
DateTime,
|
||||
DECIMAL,
|
||||
Float,
|
||||
Integer,
|
||||
String,
|
||||
TypeEngine,
|
||||
)
|
||||
|
||||
from tests.unit_tests.db_engine_specs.utils import assert_convert_dttm
|
||||
from superset.utils.core import GenericDataType
|
||||
from tests.unit_tests.db_engine_specs.utils import (
|
||||
assert_column_spec,
|
||||
assert_convert_dttm,
|
||||
)
|
||||
from tests.unit_tests.fixtures.common import dttm
|
||||
|
||||
|
||||
@@ -53,3 +67,147 @@ def test_execute_connection_error() -> None:
|
||||
)
|
||||
with pytest.raises(SupersetDBAPIDatabaseError) as ex:
|
||||
ClickHouseEngineSpec.execute(cursor, "SELECT col1 from table1")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"target_type,expected_result",
|
||||
[
|
||||
("Date", "toDate('2019-01-02')"),
|
||||
("DateTime", "toDateTime('2019-01-02 03:04:05')"),
|
||||
("UnknownType", None),
|
||||
],
|
||||
)
|
||||
def test_connect_convert_dttm(
|
||||
target_type: str, expected_result: Optional[str], dttm: datetime
|
||||
) -> None:
|
||||
from superset.db_engine_specs.clickhouse import ClickHouseEngineSpec as spec
|
||||
|
||||
assert_convert_dttm(spec, target_type, expected_result, dttm)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"native_type,sqla_type,attrs,generic_type,is_dttm",
|
||||
[
|
||||
("String", String, None, GenericDataType.STRING, False),
|
||||
("LowCardinality(String)", String, None, GenericDataType.STRING, False),
|
||||
("Nullable(String)", String, None, GenericDataType.STRING, False),
|
||||
(
|
||||
"LowCardinality(Nullable(String))",
|
||||
String,
|
||||
None,
|
||||
GenericDataType.STRING,
|
||||
False,
|
||||
),
|
||||
("Array(UInt8)", String, None, GenericDataType.STRING, False),
|
||||
("Enum('hello', 'world')", String, None, GenericDataType.STRING, False),
|
||||
("Enum('UInt32', 'Bool')", String, None, GenericDataType.STRING, False),
|
||||
(
|
||||
"LowCardinality(Enum('hello', 'world'))",
|
||||
String,
|
||||
None,
|
||||
GenericDataType.STRING,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"Nullable(Enum('hello', 'world'))",
|
||||
String,
|
||||
None,
|
||||
GenericDataType.STRING,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"LowCardinality(Nullable(Enum('hello', 'world')))",
|
||||
String,
|
||||
None,
|
||||
GenericDataType.STRING,
|
||||
False,
|
||||
),
|
||||
("FixedString(16)", String, None, GenericDataType.STRING, False),
|
||||
("Nullable(FixedString(16))", String, None, GenericDataType.STRING, False),
|
||||
(
|
||||
"LowCardinality(Nullable(FixedString(16)))",
|
||||
String,
|
||||
None,
|
||||
GenericDataType.STRING,
|
||||
False,
|
||||
),
|
||||
("UUID", String, None, GenericDataType.STRING, False),
|
||||
("Int8", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Int16", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Int32", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Int64", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Int128", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Int256", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Nullable(Int256)", Integer, None, GenericDataType.NUMERIC, False),
|
||||
(
|
||||
"LowCardinality(Nullable(Int256))",
|
||||
Integer,
|
||||
None,
|
||||
GenericDataType.NUMERIC,
|
||||
False,
|
||||
),
|
||||
("UInt8", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("UInt16", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("UInt32", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("UInt64", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("UInt128", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("UInt256", Integer, None, GenericDataType.NUMERIC, False),
|
||||
("Nullable(UInt256)", Integer, None, GenericDataType.NUMERIC, False),
|
||||
(
|
||||
"LowCardinality(Nullable(UInt256))",
|
||||
Integer,
|
||||
None,
|
||||
GenericDataType.NUMERIC,
|
||||
False,
|
||||
),
|
||||
("Float32", Float, None, GenericDataType.NUMERIC, False),
|
||||
("Float64", Float, None, GenericDataType.NUMERIC, False),
|
||||
("Decimal(1, 2)", DECIMAL, None, GenericDataType.NUMERIC, False),
|
||||
("Decimal32(2)", DECIMAL, None, GenericDataType.NUMERIC, False),
|
||||
("Decimal64(2)", DECIMAL, None, GenericDataType.NUMERIC, False),
|
||||
("Decimal128(2)", DECIMAL, None, GenericDataType.NUMERIC, False),
|
||||
("Decimal256(2)", DECIMAL, None, GenericDataType.NUMERIC, False),
|
||||
("Bool", Boolean, None, GenericDataType.BOOLEAN, False),
|
||||
("Nullable(Bool)", Boolean, None, GenericDataType.BOOLEAN, False),
|
||||
("Date", Date, None, GenericDataType.TEMPORAL, True),
|
||||
("Nullable(Date)", Date, None, GenericDataType.TEMPORAL, True),
|
||||
("LowCardinality(Nullable(Date))", Date, None, GenericDataType.TEMPORAL, True),
|
||||
("Date32", Date, None, GenericDataType.TEMPORAL, True),
|
||||
("Datetime", DateTime, None, GenericDataType.TEMPORAL, True),
|
||||
("Nullable(Datetime)", DateTime, None, GenericDataType.TEMPORAL, True),
|
||||
(
|
||||
"LowCardinality(Nullable(Datetime))",
|
||||
DateTime,
|
||||
None,
|
||||
GenericDataType.TEMPORAL,
|
||||
True,
|
||||
),
|
||||
("Datetime('UTC')", DateTime, None, GenericDataType.TEMPORAL, True),
|
||||
("Datetime64(3)", DateTime, None, GenericDataType.TEMPORAL, True),
|
||||
("Datetime64(3, 'UTC')", DateTime, None, GenericDataType.TEMPORAL, True),
|
||||
],
|
||||
)
|
||||
def test_connect_get_column_spec(
|
||||
native_type: str,
|
||||
sqla_type: Type[TypeEngine],
|
||||
attrs: Optional[Dict[str, Any]],
|
||||
generic_type: GenericDataType,
|
||||
is_dttm: bool,
|
||||
) -> None:
|
||||
from superset.db_engine_specs.clickhouse import ClickHouseConnectEngineSpec as spec
|
||||
|
||||
assert_column_spec(spec, native_type, sqla_type, attrs, generic_type, is_dttm)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"column_name,expected_result",
|
||||
[
|
||||
("time", "time_07cc69"),
|
||||
("count", "count_e2942a"),
|
||||
],
|
||||
)
|
||||
def test_connect_make_label_compatible(column_name: str, expected_result: str) -> None:
|
||||
from superset.db_engine_specs.clickhouse import ClickHouseConnectEngineSpec as spec
|
||||
|
||||
label = spec.make_label_compatible(column_name)
|
||||
assert label == expected_result
|
||||
|
||||
@@ -20,7 +20,7 @@ from textwrap import dedent
|
||||
from typing import Any, Dict, Optional, Type
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import column, table, types
|
||||
from sqlalchemy import column, table
|
||||
from sqlalchemy.dialects import mssql
|
||||
from sqlalchemy.dialects.mssql import DATE, NTEXT, NVARCHAR, TEXT, VARCHAR
|
||||
from sqlalchemy.sql import select
|
||||
@@ -50,7 +50,7 @@ from tests.unit_tests.fixtures.common import dttm
|
||||
)
|
||||
def test_get_column_spec(
|
||||
native_type: str,
|
||||
sqla_type: Type[types.TypeEngine],
|
||||
sqla_type: Type[TypeEngine],
|
||||
attrs: Optional[Dict[str, Any]],
|
||||
generic_type: GenericDataType,
|
||||
is_dttm: bool,
|
||||
|
||||
Reference in New Issue
Block a user