This is an automated email from the ASF dual-hosted git repository. maximebeauchemin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push: new 426c34e Pass granularity from backend to frontend as ISO duration (#4755) 426c34e is described below commit 426c34ee8643929cdda5a462c6d04289e73cd68b Author: Beto Dealmeida <robe...@dealmeida.net> AuthorDate: Fri Apr 6 16:19:17 2018 -0700 Pass granularity from backend to frontend as ISO duration (#4755) * Add ISO duration to time grains * Use ISO duration * Remove debugging code * Add module to yarn.lock * Remove autolint * Druid granularity as ISO * Remove dangling comma --- .../assets/javascripts/explore/stores/controls.jsx | 30 +-- superset/assets/package.json | 1 + .../visualizations/deckgl/layers/scatter.jsx | 26 +-- superset/assets/yarn.lock | 4 + superset/connectors/sqla/models.py | 2 +- superset/db_engine_specs.py | 257 +++++++++++++-------- superset/models/core.py | 2 +- 7 files changed, 183 insertions(+), 139 deletions(-) diff --git a/superset/assets/javascripts/explore/stores/controls.jsx b/superset/assets/javascripts/explore/stores/controls.jsx index 65dd2f6..b6d784e 100644 --- a/superset/assets/javascripts/explore/stores/controls.jsx +++ b/superset/assets/javascripts/explore/stores/controls.jsx @@ -699,21 +699,21 @@ export const controls = { freeForm: true, label: t('Time Granularity'), default: 'one day', - choices: formatSelectOptions([ - 'all', - '5 seconds', - '30 seconds', - '1 minute', - '5 minutes', - '1 hour', - '6 hour', - '1 day', - '7 days', - 'week', - 'week_starting_sunday', - 'week_ending_saturday', - 'month', - ]), + choices: [ + [null, 'all'], + ['PT5S', '5 seconds'], + ['PT30S', '30 seconds'], + ['PT1M', '1 minute'], + ['PT5M', '5 minutes'], + ['PT1H', '1 hour'], + ['PT6H', '6 hour'], + ['P1D', '1 day'], + ['P7D', '7 days'], + ['P1W', 'week'], + ['P1W', 'week_starting_sunday'], + ['P1W', 'week_ending_saturday'], + ['P1M', 'month'], + ], description: t('The time granularity for the visualization. Note that you ' + 'can type and use simple natural language as in `10 seconds`, ' + '`1 day` or `56 weeks`'), diff --git a/superset/assets/package.json b/superset/assets/package.json index 6d39a6b..69e36ee 100644 --- a/superset/assets/package.json +++ b/superset/assets/package.json @@ -79,6 +79,7 @@ "object.entries": "^1.0.4", "object.keys": "^0.1.0", "object.values": "^1.0.4", + "parse-iso-duration": "^1.0.0", "po2json": "^0.4.5", "prop-types": "^15.6.0", "react": "^15.6.2", diff --git a/superset/assets/visualizations/deckgl/layers/scatter.jsx b/superset/assets/visualizations/deckgl/layers/scatter.jsx index 3d8e99c..052a7ab 100644 --- a/superset/assets/visualizations/deckgl/layers/scatter.jsx +++ b/superset/assets/visualizations/deckgl/layers/scatter.jsx @@ -4,6 +4,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; +import parseIsoDuration from 'parse-iso-duration'; import { ScatterplotLayer } from 'deck.gl'; import AnimatableDeckGLContainer from '../AnimatableDeckGLContainer'; @@ -14,27 +15,6 @@ import { getColorFromScheme, hexToRGB } from '../../../javascripts/modules/color import { unitToRadius } from '../../../javascripts/modules/geo'; import sandboxedEval from '../../../javascripts/modules/sandbox'; -function getStep(timeGrain) { - // grain in milliseconds - const MINUTE = 60 * 1000; - const HOUR = 60 * MINUTE; - const DAY = 24 * HOUR; - const WEEK = 7 * DAY; - const MONTH = 30 * DAY; - const YEAR = 365 * DAY; - - const milliseconds = { - 'Time Column': MINUTE, - min: MINUTE, - hour: HOUR, - day: DAY, - week: WEEK, - month: MONTH, - year: YEAR, - }; - - return milliseconds[timeGrain]; -} function getPoints(data) { return data.map(d => d.position); @@ -117,7 +97,7 @@ class DeckGLScatter extends React.PureComponent { /* eslint-disable no-unused-vars */ static getDerivedStateFromProps(nextProps, prevState) { const fd = nextProps.slice.formData; - const timeGrain = fd.time_grain_sqla || fd.granularity || 'min'; + const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M'; // find start and end based on the data const timestamps = nextProps.payload.data.features.map(f => f.__timestamp); @@ -125,7 +105,7 @@ class DeckGLScatter extends React.PureComponent { let end = Math.max(...timestamps); // lock start and end to the closest steps - const step = getStep(timeGrain); + const step = parseIsoDuration(timeGrain); start -= start % step; end += step - end % step; diff --git a/superset/assets/yarn.lock b/superset/assets/yarn.lock index 6ca7fe1..f77c1c6 100644 --- a/superset/assets/yarn.lock +++ b/superset/assets/yarn.lock @@ -6528,6 +6528,10 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" +parse-iso-duration@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-iso-duration/-/parse-iso-duration-1.0.0.tgz#b923ab898a8ff8f42bdc9ee5db6e22808c48a864" + parse-json@^2.1.0, parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 0f1640d..7033048 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -376,7 +376,7 @@ class SqlaTable(Model, BaseDatasource): if self.type == 'table': grains = self.database.grains() or [] if grains: - grains = [(g.name, g.name) for g in grains] + grains = [(g.duration, g.name) for g in grains] d['granularity_sqla'] = utils.choicify(self.dttm_cols) d['time_grain_sqla'] = grains return d diff --git a/superset/db_engine_specs.py b/superset/db_engine_specs.py index c9006bc..85ff9db 100644 --- a/superset/db_engine_specs.py +++ b/superset/db_engine_specs.py @@ -47,7 +47,7 @@ config = app.config tracking_url_trans = conf.get('TRACKING_URL_TRANSFORMER') hive_poll_interval = conf.get('HIVE_POLL_INTERVAL') -Grain = namedtuple('Grain', 'name label function') +Grain = namedtuple('Grain', 'name label function duration') class LimitMethod(object): @@ -287,23 +287,23 @@ class PostgresBaseEngineSpec(BaseEngineSpec): engine = '' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('second', _('second'), - "DATE_TRUNC('second', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('second', {col}) AT TIME ZONE 'UTC'", 'PT1S'), Grain('minute', _('minute'), - "DATE_TRUNC('minute', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('minute', {col}) AT TIME ZONE 'UTC'", 'PT1M'), Grain('hour', _('hour'), - "DATE_TRUNC('hour', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('hour', {col}) AT TIME ZONE 'UTC'", 'PT1H'), Grain('day', _('day'), - "DATE_TRUNC('day', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('day', {col}) AT TIME ZONE 'UTC'", 'P1D'), Grain('week', _('week'), - "DATE_TRUNC('week', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('week', {col}) AT TIME ZONE 'UTC'", 'P1W'), Grain('month', _('month'), - "DATE_TRUNC('month', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('month', {col}) AT TIME ZONE 'UTC'", 'P1M'), Grain('quarter', _('quarter'), - "DATE_TRUNC('quarter', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('quarter', {col}) AT TIME ZONE 'UTC'", 'P0.25Y'), Grain('year', _('year'), - "DATE_TRUNC('year', {col}) AT TIME ZONE 'UTC'"), + "DATE_TRUNC('year', {col}) AT TIME ZONE 'UTC'", 'P1Y'), ) @classmethod @@ -346,14 +346,14 @@ class OracleEngineSpec(PostgresBaseEngineSpec): engine = 'oracle' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), - Grain('minute', _('minute'), "TRUNC(TO_DATE({col}), 'MI')"), - Grain('hour', _('hour'), "TRUNC(TO_DATE({col}), 'HH')"), - Grain('day', _('day'), "TRUNC(TO_DATE({col}), 'DDD')"), - Grain('week', _('week'), "TRUNC(TO_DATE({col}), 'WW')"), - Grain('month', _('month'), "TRUNC(TO_DATE({col}), 'MONTH')"), - Grain('quarter', _('quarter'), "TRUNC(TO_DATE({col}), 'Q')"), - Grain('year', _('year'), "TRUNC(TO_DATE({col}), 'YEAR')"), + Grain('Time Column', _('Time Column'), '{col}', None), + Grain('minute', _('minute'), "TRUNC(TO_DATE({col}), 'MI')", 'PT1M'), + Grain('hour', _('hour'), "TRUNC(TO_DATE({col}), 'HH')", 'PT1H'), + Grain('day', _('day'), "TRUNC(TO_DATE({col}), 'DDD')", 'P1D'), + Grain('week', _('week'), "TRUNC(TO_DATE({col}), 'WW')", 'P1W'), + Grain('month', _('month'), "TRUNC(TO_DATE({col}), 'MONTH')", 'P1M'), + Grain('quarter', _('quarter'), "TRUNC(TO_DATE({col}), 'Q')", 'P0.25Y'), + Grain('year', _('year'), "TRUNC(TO_DATE({col}), 'YEAR')", 'P1Y'), ) @classmethod @@ -366,36 +366,44 @@ class OracleEngineSpec(PostgresBaseEngineSpec): class Db2EngineSpec(BaseEngineSpec): engine = 'ibm_db_sa' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('second', _('second'), 'CAST({col} as TIMESTAMP)' - ' - MICROSECOND({col}) MICROSECONDS'), + ' - MICROSECOND({col}) MICROSECONDS', + 'PT1S'), Grain('minute', _('minute'), 'CAST({col} as TIMESTAMP)' ' - SECOND({col}) SECONDS' - ' - MICROSECOND({col}) MICROSECONDS'), + ' - MICROSECOND({col}) MICROSECONDS', + 'PT1M'), Grain('hour', _('hour'), 'CAST({col} as TIMESTAMP)' ' - MINUTE({col}) MINUTES' ' - SECOND({col}) SECONDS' - ' - MICROSECOND({col}) MICROSECONDS '), + ' - MICROSECOND({col}) MICROSECONDS ', + 'PT1H'), Grain('day', _('day'), 'CAST({col} as TIMESTAMP)' ' - HOUR({col}) HOURS' ' - MINUTE({col}) MINUTES' ' - SECOND({col}) SECONDS' - ' - MICROSECOND({col}) MICROSECONDS '), + ' - MICROSECOND({col}) MICROSECONDS ', + 'P1D'), Grain('week', _('week'), - '{col} - (DAYOFWEEK({col})) DAYS'), + '{col} - (DAYOFWEEK({col})) DAYS', + 'P1W'), Grain('month', _('month'), - '{col} - (DAY({col})-1) DAYS'), + '{col} - (DAY({col})-1) DAYS', + 'P1M'), Grain('quarter', _('quarter'), '{col} - (DAY({col})-1) DAYS' ' - (MONTH({col})-1) MONTHS' - ' + ((QUARTER({col})-1) * 3) MONTHS'), + ' + ((QUARTER({col})-1) * 3) MONTHS', + 'P0.25Y'), Grain('year', _('year'), '{col} - (DAY({col})-1) DAYS' - ' - (MONTH({col})-1) MONTHS'), + ' - (MONTH({col})-1) MONTHS', + 'P1Y'), ) @classmethod @@ -410,14 +418,17 @@ class Db2EngineSpec(BaseEngineSpec): class SqliteEngineSpec(BaseEngineSpec): engine = 'sqlite' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('hour', _('hour'), - "DATETIME(STRFTIME('%Y-%m-%dT%H:00:00', {col}))"), - Grain('day', _('day'), 'DATE({col})'), + "DATETIME(STRFTIME('%Y-%m-%dT%H:00:00', {col}))", + 'PT1H'), + Grain('day', _('day'), 'DATE({col})', 'P1D'), Grain('week', _('week'), - "DATE({col}, -strftime('%w', {col}) || ' days')"), + "DATE({col}, -strftime('%w', {col}) || ' days')", + 'P1W'), Grain('month', _('month'), - "DATE({col}, -strftime('%d', {col}) || ' days', '+1 day')"), + "DATE({col}, -strftime('%d', {col}) || ' days', '+1 day')", + 'P1M'), ) @classmethod @@ -460,26 +471,34 @@ class MySQLEngineSpec(BaseEngineSpec): engine = 'mysql' cursor_execute_kwargs = {'args': {}} time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('second', _('second'), 'DATE_ADD(DATE({col}), ' 'INTERVAL (HOUR({col})*60*60 + MINUTE({col})*60' - ' + SECOND({col})) SECOND)'), + ' + SECOND({col})) SECOND)', + 'PT1S'), Grain('minute', _('minute'), 'DATE_ADD(DATE({col}), ' - 'INTERVAL (HOUR({col})*60 + MINUTE({col})) MINUTE)'), + 'INTERVAL (HOUR({col})*60 + MINUTE({col})) MINUTE)', + 'PT1M'), Grain('hour', _('hour'), 'DATE_ADD(DATE({col}), ' - 'INTERVAL HOUR({col}) HOUR)'), - Grain('day', _('day'), 'DATE({col})'), + 'INTERVAL HOUR({col}) HOUR)', + 'PT1H'), + Grain('day', _('day'), 'DATE({col})', 'P1D'), Grain('week', _('week'), 'DATE(DATE_SUB({col}, ' - 'INTERVAL DAYOFWEEK({col}) - 1 DAY))'), + 'INTERVAL DAYOFWEEK({col}) - 1 DAY))', + 'P1W'), Grain('month', _('month'), 'DATE(DATE_SUB({col}, ' - 'INTERVAL DAYOFMONTH({col}) - 1 DAY))'), + 'INTERVAL DAYOFMONTH({col}) - 1 DAY))', + 'P1M'), Grain('quarter', _('quarter'), 'MAKEDATE(YEAR({col}), 1) ' - '+ INTERVAL QUARTER({col}) QUARTER - INTERVAL 1 QUARTER'), + '+ INTERVAL QUARTER({col}) QUARTER - INTERVAL 1 QUARTER', + 'P0.25Y'), Grain('year', _('year'), 'DATE(DATE_SUB({col}, ' - 'INTERVAL DAYOFYEAR({col}) - 1 DAY))'), + 'INTERVAL DAYOFYEAR({col}) - 1 DAY))', + 'P1Y'), Grain('week_start_monday', _('week_start_monday'), 'DATE(DATE_SUB({col}, ' - 'INTERVAL DAYOFWEEK(DATE_SUB({col}, INTERVAL 1 DAY)) - 1 DAY))'), + 'INTERVAL DAYOFWEEK(DATE_SUB({col}, INTERVAL 1 DAY)) - 1 DAY))', + 'P1W'), ) @classmethod @@ -516,27 +535,39 @@ class PrestoEngineSpec(BaseEngineSpec): cursor_execute_kwargs = {'parameters': None} time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('second', _('second'), - "date_trunc('second', CAST({col} AS TIMESTAMP))"), + "date_trunc('second', CAST({col} AS TIMESTAMP))", + 'PT1S'), Grain('minute', _('minute'), - "date_trunc('minute', CAST({col} AS TIMESTAMP))"), + "date_trunc('minute', CAST({col} AS TIMESTAMP))", + 'PT1M'), Grain('hour', _('hour'), - "date_trunc('hour', CAST({col} AS TIMESTAMP))"), + "date_trunc('hour', CAST({col} AS TIMESTAMP))", + 'PT1H'), Grain('day', _('day'), - "date_trunc('day', CAST({col} AS TIMESTAMP))"), + "date_trunc('day', CAST({col} AS TIMESTAMP))", + 'P1D'), Grain('week', _('week'), - "date_trunc('week', CAST({col} AS TIMESTAMP))"), + "date_trunc('week', CAST({col} AS TIMESTAMP))", + 'P1W'), Grain('month', _('month'), - "date_trunc('month', CAST({col} AS TIMESTAMP))"), + "date_trunc('month', CAST({col} AS TIMESTAMP))", + 'P1M'), Grain('quarter', _('quarter'), - "date_trunc('quarter', CAST({col} AS TIMESTAMP))"), + "date_trunc('quarter', CAST({col} AS TIMESTAMP))", + 'P0.25Y'), Grain('week_ending_saturday', _('week_ending_saturday'), "date_add('day', 5, date_trunc('week', date_add('day', 1, " - 'CAST({col} AS TIMESTAMP))))'), + 'CAST({col} AS TIMESTAMP))))', + 'P1W'), Grain('week_start_sunday', _('week_start_sunday'), "date_add('day', -1, date_trunc('week', " - "date_add('day', 1, CAST({col} AS TIMESTAMP))))"), + "date_add('day', 1, CAST({col} AS TIMESTAMP))))", + 'P1W'), + Grain('year', _('year'), + "date_trunc('year', CAST({col} AS TIMESTAMP))", + 'P1Y'), ) @classmethod @@ -1054,27 +1085,37 @@ class MssqlEngineSpec(BaseEngineSpec): epoch_to_dttm = "dateadd(S, {col}, '1970-01-01')" time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('second', _('second'), 'DATEADD(second, ' - "DATEDIFF(second, '2000-01-01', {col}), '2000-01-01')"), + "DATEDIFF(second, '2000-01-01', {col}), '2000-01-01')", + 'PT1S'), Grain('minute', _('minute'), 'DATEADD(minute, ' - 'DATEDIFF(minute, 0, {col}), 0)'), + 'DATEDIFF(minute, 0, {col}), 0)', + 'PT1M'), Grain('5 minute', _('5 minute'), 'DATEADD(minute, ' - 'DATEDIFF(minute, 0, {col}) / 5 * 5, 0)'), + 'DATEDIFF(minute, 0, {col}) / 5 * 5, 0)', + 'PT5M'), Grain('half hour', _('half hour'), 'DATEADD(minute, ' - 'DATEDIFF(minute, 0, {col}) / 30 * 30, 0)'), + 'DATEDIFF(minute, 0, {col}) / 30 * 30, 0)', + 'PT0.5H'), Grain('hour', _('hour'), 'DATEADD(hour, ' - 'DATEDIFF(hour, 0, {col}), 0)'), + 'DATEDIFF(hour, 0, {col}), 0)', + 'PT1H'), Grain('day', _('day'), 'DATEADD(day, ' - 'DATEDIFF(day, 0, {col}), 0)'), + 'DATEDIFF(day, 0, {col}), 0)', + 'P1D'), Grain('week', _('week'), 'DATEADD(week, ' - 'DATEDIFF(week, 0, {col}), 0)'), + 'DATEDIFF(week, 0, {col}), 0)', + 'P1W'), Grain('month', _('month'), 'DATEADD(month, ' - 'DATEDIFF(month, 0, {col}), 0)'), + 'DATEDIFF(month, 0, {col}), 0)', + 'P1M'), Grain('quarter', _('quarter'), 'DATEADD(quarter, ' - 'DATEDIFF(quarter, 0, {col}), 0)'), + 'DATEDIFF(quarter, 0, {col}), 0)', + 'P0.25Y'), Grain('year', _('year'), 'DATEADD(year, ' - 'DATEDIFF(year, 0, {col}), 0)'), + 'DATEDIFF(year, 0, {col}), 0)', + 'P1Y'), ) @classmethod @@ -1086,27 +1127,36 @@ class AthenaEngineSpec(BaseEngineSpec): engine = 'awsathena' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('second', _('second'), - "date_trunc('second', CAST({col} AS TIMESTAMP))"), + "date_trunc('second', CAST({col} AS TIMESTAMP))", + 'PT1S'), Grain('minute', _('minute'), - "date_trunc('minute', CAST({col} AS TIMESTAMP))"), + "date_trunc('minute', CAST({col} AS TIMESTAMP))", + 'PT1M'), Grain('hour', _('hour'), - "date_trunc('hour', CAST({col} AS TIMESTAMP))"), + "date_trunc('hour', CAST({col} AS TIMESTAMP))", + 'PT1H'), Grain('day', _('day'), - "date_trunc('day', CAST({col} AS TIMESTAMP))"), + "date_trunc('day', CAST({col} AS TIMESTAMP))", + 'P1D'), Grain('week', _('week'), - "date_trunc('week', CAST({col} AS TIMESTAMP))"), + "date_trunc('week', CAST({col} AS TIMESTAMP))", + 'P1W'), Grain('month', _('month'), - "date_trunc('month', CAST({col} AS TIMESTAMP))"), + "date_trunc('month', CAST({col} AS TIMESTAMP))", + 'P1M'), Grain('quarter', _('quarter'), - "date_trunc('quarter', CAST({col} AS TIMESTAMP))"), + "date_trunc('quarter', CAST({col} AS TIMESTAMP))", + 'P0.25Y'), Grain('week_ending_saturday', _('week_ending_saturday'), "date_add('day', 5, date_trunc('week', date_add('day', 1, " - 'CAST({col} AS TIMESTAMP))))'), + 'CAST({col} AS TIMESTAMP))))', + 'P1W'), Grain('week_start_sunday', _('week_start_sunday'), "date_add('day', -1, date_trunc('week', " - "date_add('day', 1, CAST({col} AS TIMESTAMP))))"), + "date_add('day', 1, CAST({col} AS TIMESTAMP))))", + 'P1W'), ) @classmethod @@ -1132,23 +1182,31 @@ class ClickHouseEngineSpec(BaseEngineSpec): time_secondary_columns = True time_groupby_inline = True time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), + Grain('Time Column', _('Time Column'), '{col}', None), Grain('minute', _('minute'), - 'toStartOfMinute(toDateTime({col}))'), + 'toStartOfMinute(toDateTime({col}))', + 'PT1M'), Grain('5 minute', _('5 minute'), - 'toDateTime(intDiv(toUInt32(toDateTime({col})), 300)*300)'), + 'toDateTime(intDiv(toUInt32(toDateTime({col})), 300)*300)', + 'PT5M'), Grain('10 minute', _('10 minute'), - 'toDateTime(intDiv(toUInt32(toDateTime({col})), 600)*600)'), + 'toDateTime(intDiv(toUInt32(toDateTime({col})), 600)*600)', + 'PT10M'), Grain('hour', _('hour'), - 'toStartOfHour(toDateTime({col}))'), + 'toStartOfHour(toDateTime({col}))', + 'PT1H'), Grain('day', _('day'), - 'toStartOfDay(toDateTime({col}))'), + 'toStartOfDay(toDateTime({col}))', + 'P1D'), Grain('month', _('month'), - 'toStartOfMonth(toDateTime({col}))'), + 'toStartOfMonth(toDateTime({col}))', + 'P1M'), Grain('quarter', _('quarter'), - 'toStartOfQuarter(toDateTime({col}))'), + 'toStartOfQuarter(toDateTime({col}))', + 'P0.25Y'), Grain('year', _('year'), - 'toStartOfYear(toDateTime({col}))'), + 'toStartOfYear(toDateTime({col}))', + 'P1Y'), ) @classmethod @@ -1169,15 +1227,16 @@ class BQEngineSpec(BaseEngineSpec): engine = 'bigquery' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), - Grain('second', _('second'), 'TIMESTAMP_TRUNC({col}, SECOND)'), - Grain('minute', _('minute'), 'TIMESTAMP_TRUNC({col}, MINUTE)'), - Grain('hour', _('hour'), 'TIMESTAMP_TRUNC({col}, HOUR)'), - Grain('day', _('day'), 'TIMESTAMP_TRUNC({col}, DAY)'), - Grain('week', _('week'), 'TIMESTAMP_TRUNC({col}, WEEK)'), - Grain('month', _('month'), 'TIMESTAMP_TRUNC({col}, MONTH)'), - Grain('quarter', _('quarter'), 'TIMESTAMP_TRUNC({col}, QUARTER)'), - Grain('year', _('year'), 'TIMESTAMP_TRUNC({col}, YEAR)'), + Grain('Time Column', _('Time Column'), '{col}', None), + Grain('second', _('second'), 'TIMESTAMP_TRUNC({col}, SECOND)', 'PT1S'), + Grain('minute', _('minute'), 'TIMESTAMP_TRUNC({col}, MINUTE)', 'PT1M'), + Grain('hour', _('hour'), 'TIMESTAMP_TRUNC({col}, HOUR)', 'PT1H'), + Grain('day', _('day'), 'TIMESTAMP_TRUNC({col}, DAY)', 'P1D'), + Grain('week', _('week'), 'TIMESTAMP_TRUNC({col}, WEEK)', 'P1W'), + Grain('month', _('month'), 'TIMESTAMP_TRUNC({col}, MONTH)', 'P1M'), + Grain('quarter', _('quarter'), + 'TIMESTAMP_TRUNC({col}, QUARTER)', 'P0.25Y'), + Grain('year', _('year'), 'TIMESTAMP_TRUNC({col}, YEAR)', 'P1Y'), ) @classmethod @@ -1201,14 +1260,14 @@ class ImpalaEngineSpec(BaseEngineSpec): engine = 'impala' time_grains = ( - Grain('Time Column', _('Time Column'), '{col}'), - Grain('minute', _('minute'), "TRUNC({col}, 'MI')"), - Grain('hour', _('hour'), "TRUNC({col}, 'HH')"), - Grain('day', _('day'), "TRUNC({col}, 'DD')"), - Grain('week', _('week'), "TRUNC({col}, 'WW')"), - Grain('month', _('month'), "TRUNC({col}, 'MONTH')"), - Grain('quarter', _('quarter'), "TRUNC({col}, 'Q')"), - Grain('year', _('year'), "TRUNC({col}, 'YYYY')"), + Grain('Time Column', _('Time Column'), '{col}', None), + Grain('minute', _('minute'), "TRUNC({col}, 'MI')", 'PT1M'), + Grain('hour', _('hour'), "TRUNC({col}, 'HH')", 'PT1H'), + Grain('day', _('day'), "TRUNC({col}, 'DD')", 'P1D'), + Grain('week', _('week'), "TRUNC({col}, 'WW')", 'P1W'), + Grain('month', _('month'), "TRUNC({col}, 'MONTH')", 'P1M'), + Grain('quarter', _('quarter'), "TRUNC({col}, 'Q')", 'P0.25Y'), + Grain('year', _('year'), "TRUNC({col}, 'YYYY')", 'P1Y'), ) @classmethod diff --git a/superset/models/core.py b/superset/models/core.py index 6eef48c..5ff737e 100644 --- a/superset/models/core.py +++ b/superset/models/core.py @@ -786,7 +786,7 @@ class Database(Model, AuditMixinNullable, ImportMixin): return self.db_engine_spec.time_grains def grains_dict(self): - return {grain.name: grain for grain in self.grains()} + return {grain.duration: grain for grain in self.grains()} def get_extra(self): extra = {} -- To stop receiving notification emails like this one, please contact maximebeauche...@apache.org.