diff --git a/UPDATING.md b/UPDATING.md
index 51133dd198c6f..89741d362d9e3 100644
--- a/UPDATING.md
+++ b/UPDATING.md
@@ -27,6 +27,11 @@ assists people when migrating to a new version.
make all Unix timestamp (which by definition are in UTC) comparisons refer
to a timestamp in UTC as opposed to local time.
+* [7653](https://github.com/apache/incubator-superset/pull/7653): a change
+which deprecates the table_columns.database_expression column. Expressions
+should be handled by the DB engine spec conversion, Python date format, or
+custom column expression/type.
+
* [5451](https://github.com/apache/incubator-superset/pull/5451): a change
which adds missing non-nullable fields to the `datasources` table. Depending on
the integrity of the data, manual intervention may be required.
diff --git a/superset/assets/src/datasource/DatasourceEditor.jsx b/superset/assets/src/datasource/DatasourceEditor.jsx
index 57eb1be77c32e..eb3c25b70bc5f 100644
--- a/superset/assets/src/datasource/DatasourceEditor.jsx
+++ b/superset/assets/src/datasource/DatasourceEditor.jsx
@@ -104,28 +104,7 @@ function ColumnCollectionTable({
{t('python datetime string pattern')}
{t(` expression. If time is stored in epoch format, put \`epoch_s\` or
- \`epoch_ms\`. Leave \`Database Expression\`
- below empty if timestamp is stored in '
- String or Integer(epoch) type`)}
-
- }
- control={}
- />
-
- {t(`
- The database expression to cast internal datetime
- constants to database date/timestamp type according to the DBAPI.
- The expression should follow the pattern of
- %Y-%m-%d %H:%M:%S, based on different DBAPI.
- The string should be a python string formatter
- \`Ex: TO_DATE('{}', 'YYYY-MM-DD HH24:MI:SS')\` for Oracle
- Superset uses default expression based on DB URI if this
- field is blank.
- `)}
+ \`epoch_ms\`.`)}
}
control={}
diff --git a/superset/connectors/base/models.py b/superset/connectors/base/models.py
index 2a5fbc7f23928..e90d5d3fcd561 100644
--- a/superset/connectors/base/models.py
+++ b/superset/connectors/base/models.py
@@ -394,7 +394,6 @@ def data(self):
"groupby",
"is_dttm",
"type",
- "database_expression",
"python_date_format",
)
return {s: getattr(self, s) for s in attrs if hasattr(self, s)}
diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py
index f465b3e1a99ef..40eb25e02ecd7 100644
--- a/superset/connectors/sqla/models.py
+++ b/superset/connectors/sqla/models.py
@@ -112,7 +112,6 @@ class TableColumn(Model, BaseColumn):
is_dttm = Column(Boolean, default=False)
expression = Column(Text)
python_date_format = Column(String(255))
- database_expression = Column(String(255))
export_fields = (
"table_id",
@@ -126,7 +125,6 @@ class TableColumn(Model, BaseColumn):
"expression",
"description",
"python_date_format",
- "database_expression",
)
update_from_object_fields = [s for s in export_fields if s not in ("table_id",)]
@@ -195,18 +193,9 @@ def lookup_obj(lookup_column):
return import_datasource.import_simple_obj(db.session, i_column, lookup_obj)
def dttm_sql_literal(self, dttm):
- """Convert datetime object to a SQL expression string
-
- If database_expression is empty, the internal dttm
- will be parsed as the string with the pattern that
- the user inputted (python_date_format)
- If database_expression is not empty, the internal dttm
- will be parsed as the sql sentence for the database to convert
- """
+ """Convert datetime object to a SQL expression string"""
tf = self.python_date_format
- if self.database_expression:
- return self.database_expression.format(dttm.strftime("%Y-%m-%d %H:%M:%S"))
- elif tf:
+ if tf:
seconds_since_epoch = int(dttm.timestamp())
if tf == "epoch_s":
return str(seconds_since_epoch)
diff --git a/superset/connectors/sqla/views.py b/superset/connectors/sqla/views.py
index 90ac4e8b38d03..0600dfe0c5f9d 100644
--- a/superset/connectors/sqla/views.py
+++ b/superset/connectors/sqla/views.py
@@ -65,7 +65,6 @@ class TableColumnInlineView(CompactCRUDMixin, SupersetModelView): # noqa
"expression",
"is_dttm",
"python_date_format",
- "database_expression",
]
add_columns = edit_columns
list_columns = [
@@ -105,23 +104,10 @@ class TableColumnInlineView(CompactCRUDMixin, SupersetModelView): # noqa
'datetime.html#strftime-strptime-behavior">'
"python datetime string pattern "
"expression. If time is stored in epoch "
- "format, put `epoch_s` or `epoch_ms`. Leave `Database Expression` "
- "below empty if timestamp is stored in "
- "String or Integer(epoch) type"
+ "format, put `epoch_s` or `epoch_ms`."
),
True,
),
- "database_expression": utils.markdown(
- "The database expression to cast internal datetime "
- "constants to database date/timestamp type according to the DBAPI. "
- "The expression should follow the pattern of "
- "%Y-%m-%d %H:%M:%S, based on different DBAPI. "
- "The string should be a python string formatter \n"
- "`Ex: TO_DATE('{}', 'YYYY-MM-DD HH24:MI:SS')` for Oracle "
- "Superset uses default expression based on DB URI if this "
- "field is blank.",
- True,
- ),
}
label_columns = {
"column_name": _("Column"),
@@ -133,7 +119,6 @@ class TableColumnInlineView(CompactCRUDMixin, SupersetModelView): # noqa
"expression": _("Expression"),
"is_dttm": _("Is temporal"),
"python_date_format": _("Datetime Format"),
- "database_expression": _("Database Expression"),
"type": _("Type"),
}
diff --git a/superset/migrations/versions/b4a38aa87893_deprecate_database_expression.py b/superset/migrations/versions/b4a38aa87893_deprecate_database_expression.py
new file mode 100644
index 0000000000000..46c2ad1d7e049
--- /dev/null
+++ b/superset/migrations/versions/b4a38aa87893_deprecate_database_expression.py
@@ -0,0 +1,40 @@
+# 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.
+"""deprecate database expression
+
+Revision ID: b4a38aa87893
+Revises: ab8c66efdd01
+Create Date: 2019-06-05 11:35:16.222519
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = "b4a38aa87893"
+down_revision = "ab8c66efdd01"
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ with op.batch_alter_table("table_columns") as batch_op:
+ batch_op.drop_column("database_expression")
+
+
+def downgrade():
+ with op.batch_alter_table("table_columns") as batch_op:
+ batch_op.add_column(sa.Column("database_expression", sa.String(255)))
diff --git a/tests/fixtures/datasource.py b/tests/fixtures/datasource.py
index b2633290e3576..f09332dd78db7 100644
--- a/tests/fixtures/datasource.py
+++ b/tests/fixtures/datasource.py
@@ -39,7 +39,6 @@
"groupby": True,
"is_dttm": True,
"type": "DATETIME",
- "database_expression": "",
},
{
"id": 505,
@@ -51,7 +50,6 @@
"groupby": True,
"is_dttm": False,
"type": "VARCHAR(16)",
- "database_expression": None,
},
{
"id": 506,
@@ -63,7 +61,6 @@
"groupby": True,
"is_dttm": None,
"type": "VARCHAR(255)",
- "database_expression": None,
},
{
"id": 508,
@@ -75,7 +72,6 @@
"groupby": True,
"is_dttm": None,
"type": "VARCHAR(10)",
- "database_expression": None,
},
{
"id": 509,
@@ -87,7 +83,6 @@
"groupby": True,
"is_dttm": None,
"type": "BIGINT(20)",
- "database_expression": None,
},
{
"id": 510,
@@ -99,7 +94,6 @@
"groupby": False,
"is_dttm": False,
"type": "BIGINT(20)",
- "database_expression": None,
},
{
"id": 532,
@@ -111,7 +105,6 @@
"groupby": True,
"is_dttm": None,
"type": "BIGINT(20)",
- "database_expression": None,
},
{
"id": 522,
@@ -123,7 +116,6 @@
"groupby": False,
"is_dttm": False,
"type": "NUMBER",
- "database_expression": None,
},
],
"metrics": [