diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index e788ce7c2..64933708d 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -885,6 +885,7 @@ class SqlaTable(Model, BaseDatasource): M = SqlMetric # noqa metrics = [] any_date_col = None + db_engine_spec = self.database.db_engine_spec db_dialect = self.database.get_dialect() dbcols = ( db.session.query(TableColumn) @@ -907,6 +908,7 @@ class SqlaTable(Model, BaseDatasource): dbcol.sum = dbcol.is_num dbcol.avg = dbcol.is_num dbcol.is_dttm = dbcol.is_time + db_engine_spec.alter_new_orm_column(dbcol) else: dbcol.type = datatype dbcol.groupby = True diff --git a/superset/db_engine_specs.py b/superset/db_engine_specs.py index 6412d1044..64bffe75b 100644 --- a/superset/db_engine_specs.py +++ b/superset/db_engine_specs.py @@ -152,6 +152,15 @@ class BaseEngineSpec(object): return cursor.fetchmany(limit) return cursor.fetchall() + @classmethod + def alter_new_orm_column(cls, orm_col): + """Allow altering default column attributes when first detected/added + + For instance special column like `__time` for Druid can be + set to is_dttm=True. Note that this only gets called when new + columns are detected/created""" + pass + @classmethod def epoch_to_dttm(cls): raise NotImplementedError() @@ -1708,6 +1717,11 @@ class DruidEngineSpec(BaseEngineSpec): 'P1Y': 'FLOOR({col} TO YEAR)', } + @classmethod + def alter_new_orm_column(cls, orm_col): + if orm_col.column_name == '__time': + orm_col.is_dttm = True + class GSheetsEngineSpec(SqliteEngineSpec): """Engine for Google spreadsheets""" diff --git a/tests/sqla_models_tests.py b/tests/sqla_models_tests.py new file mode 100644 index 000000000..7d183d0f5 --- /dev/null +++ b/tests/sqla_models_tests.py @@ -0,0 +1,42 @@ +# 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 superset.connectors.sqla.models import TableColumn +from superset.db_engine_specs import DruidEngineSpec +from .base_tests import SupersetTestCase + + +class DatabaseModelTestCase(SupersetTestCase): + + def test_is_time_druid_time_col(self): + """Druid has a special __time column""" + col = TableColumn(column_name='__time', type='INTEGER') + self.assertEquals(col.is_dttm, None) + DruidEngineSpec.alter_new_orm_column(col) + self.assertEquals(col.is_dttm, True) + + col = TableColumn(column_name='__not_time', type='INTEGER') + self.assertEquals(col.is_time, False) + + def test_is_time_by_type(self): + col = TableColumn(column_name='foo', type='DATE') + self.assertEquals(col.is_time, True) + + col = TableColumn(column_name='foo', type='DATETIME') + self.assertEquals(col.is_time, True) + + col = TableColumn(column_name='foo', type='STRING') + self.assertEquals(col.is_time, False)