diff --git a/docs/static/img/databases/apache-iotdb.svg b/docs/static/img/databases/apache-iotdb.svg new file mode 100644 index 00000000000..d7426307378 --- /dev/null +++ b/docs/static/img/databases/apache-iotdb.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/static/img/databases/apache-phoenix.png b/docs/static/img/databases/apache-phoenix.png new file mode 100644 index 00000000000..9a1e8ca51da Binary files /dev/null and b/docs/static/img/databases/apache-phoenix.png differ diff --git a/superset/db_engine_specs/iotdb.py b/superset/db_engine_specs/iotdb.py new file mode 100644 index 00000000000..dbc59518715 --- /dev/null +++ b/superset/db_engine_specs/iotdb.py @@ -0,0 +1,59 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +from superset.db_engine_specs.base import BaseEngineSpec, DatabaseCategory + + +class IoTDBEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method + """Dialect for Apache IoTDB""" + + engine = "iotdb" + engine_name = "Apache IoTDB" + + metadata = { + "description": ( + "Apache IoTDB is a time series database designed for IoT data, " + "with efficient storage and query capabilities for massive " + "time series data." + ), + "logo": "apache-iotdb.svg", + "homepage_url": "https://iotdb.apache.org/", + "categories": [ + DatabaseCategory.APACHE_PROJECTS, + DatabaseCategory.TIME_SERIES, + DatabaseCategory.OPEN_SOURCE, + ], + "pypi_packages": ["apache-iotdb"], + "connection_string": "iotdb://{username}:{password}@{hostname}:{port}", + "default_port": 6667, + "parameters": { + "username": "Database username (default: root)", + "password": "Database password (default: root)", + "hostname": "IP address or hostname", + "port": "Default 6667", + }, + "notes": ( + "The IoTDB SQLAlchemy dialect was written to integrate with " + "Apache Superset. IoTDB uses a hierarchical data model, which " + "is reorganized into a relational model for SQL queries." + ), + } + + _time_grain_expressions = { + None: "{col}", + } diff --git a/superset/db_engine_specs/phoenix.py b/superset/db_engine_specs/phoenix.py new file mode 100644 index 00000000000..bb02c4c5dfb --- /dev/null +++ b/superset/db_engine_specs/phoenix.py @@ -0,0 +1,86 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +from datetime import datetime +from typing import Any, Optional + +from sqlalchemy import types + +from superset.constants import TimeGrain +from superset.db_engine_specs.base import BaseEngineSpec, DatabaseCategory + + +class PhoenixEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method + """Dialect for Apache Phoenix""" + + engine = "phoenix" + engine_name = "Apache Phoenix" + + metadata = { + "description": ( + "Apache Phoenix is a relational database layer over Apache HBase, " + "providing low-latency SQL queries over HBase data." + ), + "logo": "apache-phoenix.png", + "homepage_url": "https://phoenix.apache.org/", + "categories": [ + DatabaseCategory.APACHE_PROJECTS, + DatabaseCategory.ANALYTICAL_DATABASES, + DatabaseCategory.OPEN_SOURCE, + ], + "pypi_packages": ["phoenixdb"], + "connection_string": "phoenix://{hostname}:{port}/", + "default_port": 8765, + "notes": ( + "Phoenix provides a SQL interface to Apache HBase. " + "The phoenixdb driver connects via the Phoenix Query Server " + "and supports a subset of SQLAlchemy." + ), + } + + _time_grain_expressions = { + None: "{col}", + TimeGrain.SECOND: ( + "CAST(TRUNC(CAST({col} AS TIMESTAMP), 'SECOND') AS TIMESTAMP)" + ), + TimeGrain.MINUTE: ( + "CAST(TRUNC(CAST({col} AS TIMESTAMP), 'MINUTE') AS TIMESTAMP)" + ), + TimeGrain.HOUR: ("CAST(TRUNC(CAST({col} AS TIMESTAMP), 'HOUR') AS TIMESTAMP)"), + TimeGrain.DAY: "CAST(TRUNC(CAST({col} AS TIMESTAMP), 'DAY') AS DATE)", + TimeGrain.WEEK: "CAST(TRUNC(CAST({col} AS TIMESTAMP), 'WEEK') AS DATE)", + TimeGrain.MONTH: ("CAST(TRUNC(CAST({col} AS TIMESTAMP), 'MONTH') AS DATE)"), + TimeGrain.QUARTER: ("CAST(TRUNC(CAST({col} AS TIMESTAMP), 'QUARTER') AS DATE)"), + TimeGrain.YEAR: "CAST(TRUNC(CAST({col} AS TIMESTAMP), 'YEAR') AS DATE)", + } + + @classmethod + def convert_dttm( + cls, + target_type: str, + dttm: datetime, + db_extra: Optional[dict[str, Any]] = None, + ) -> Optional[str]: + sqla_type = cls.get_sqla_column_type(target_type) + + if isinstance(sqla_type, types.Date): + return f"TO_DATE('{dttm.date().isoformat()}', 'yyyy-MM-dd')" + if isinstance(sqla_type, (types.DateTime, types.TIMESTAMP)): + datetime_formatted = dttm.isoformat(sep=" ", timespec="seconds") + return f"TO_TIMESTAMP('{datetime_formatted}', 'yyyy-MM-dd HH:mm:ss')" + return None