-
Notifications
You must be signed in to change notification settings - Fork 14.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Default temporal column in Datasource #21857
Conversation
Codecov Report
@@ Coverage Diff @@
## master #21857 +/- ##
==========================================
- Coverage 66.85% 66.74% -0.12%
==========================================
Files 1805 1810 +5
Lines 69061 71385 +2324
Branches 7369 8232 +863
==========================================
+ Hits 46169 47644 +1475
- Misses 20995 21703 +708
- Partials 1897 2038 +141
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx
Show resolved
Hide resolved
const timeCol = this.props.form_data?.granularity_sqla; | ||
const { columns } = this.props.datasource; | ||
const firstDttmCol = columns.find(column => column.is_dttm); | ||
if ( | ||
datasource.type === 'table' && | ||
!columns.find(({ column_name }) => column_name === timeCol)?.is_dttm | ||
) { | ||
// set `granularity_sqla` to first datatime column name or null | ||
this.props.actions.setControlValue( | ||
'granularity_sqla', | ||
firstDttmCol ? firstDttmCol.column_name : null, | ||
); | ||
const timeCol = this.props.form_data?.granularity_sqla; | ||
const timeColConf = columns.find( | ||
({ column_name }) => column_name === timeCol, | ||
); | ||
if (datasource.type === 'table') { | ||
// resets new default time col or picks the first available one | ||
if (!timeColConf?.is_dttm) { | ||
const setDttmCol = getTemporalColumns(this.props.datasource); | ||
this.props.actions.setControlValue( | ||
'granularity_sqla', | ||
setDttmCol.defaultTemporalColumn, | ||
); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getTemporalColumns will return a well-designed data structure so the below snippet will handle it. this logic is same as dndGranularitySqlaControl
. notice that the granularity_sqla
default value is null
.
const {temporalColumns, defaultTemporalColumn} = getTemporalColumns(this.props.datasource)
this.props.actions.setControlValue(
'granularity_sqla',
defaultTemporalColumn ?? temporalColumns?.[0] ?? null,
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhaoyongjie I still need to check if the current time col is null, because I only want to replace the existing value if that is null, not otherwise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@geido timeColConf
must be a time column, otherwise it wouldn't be set to granularity_sqla
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@geido i jsut reread this codes. the datasource
is new datasource setting, so we should use the new datasouce instead of this.props.datasouce
.
const {temporalColumns, defaultTemporalColumn} = getTemporalColumns(datasource)
this.props.actions.setControlValue(
'granularity_sqla',
defaultTemporalColumn ?? temporalColumns?.[0] ?? null,
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhaoyongjie granularity_sqla
can indeed return also a column that is not a time column anymore after the user has unselected the "Is temporal" from the dataset. To try, just select a default time column for the time column control, then edit the dataset and keep the column as default but remove the "Is temporal" flag, you will see that granularity_sqla
will still return that value as if it was temporal as indeed that's the last value known when saving the dataset.
That's useful because we want to change the control value only when it's empty. This is a product requirement that I confirmed with Kasia as well.
I also found out that the getTemporalColumns
util isn't working properly. It's setting as default temporal column also columns that are not temporal anymore. In fact, the datasource.main_dttm_col
can hold a column that was kept as default but removed from "Is temporal". I think this requires a fix in the util itself, but for now I am just making an additional check in my code to account for this issue as I don't want to potentially cause troubles to other parts of the application that are using that util.
I made some more improvements to the code but I believe this should be ready to go. I will spin up a testenv if you want to manual test it.
The product requirements for manual testing are the following:
- If the control is empty, change it with the new default or the first time column found if no default is there
- If the control is not empty, changing the default will only affect the dataset but not the control which will keep the existing value
- If the column that is currently used in the control is removed from the dataset as time column and if there is no other time column available, the control should be emptied
Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@geido Thank you for the explanation. I understand what you are saying. This has been a long-time-coming issue in the Superset.
The main_dttm_col
is saved in the tables
table on the Superset metadata. According to Superset's original design(for Druid native query), each dataset must have a main_dttm_col
, it is granularity_sqla
in the frontend, AKA time column.
Every column in the datasource is saved in the table_columns
table, it has a column is_dttm
for is_temporal usages.
the time column query order is
main_dttm_col
.- Arbitrary column is in
table_columns
and is_dttm is true.
The issue should be that even if we unselected the default column's is_dttm
attribute, it is still saved in the main_dttm_col
column. We should fix this logic --- remove a non-temporal recorded from main_dttm_col, and not just ignore main_dttm_col on the frontend, which would cause inconsistencies between the front and backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhaoyongjie I understand that but the fix would be out of scope right now. I need to get the fix for the control out first and I can open a separate issue to investigate the core problem that you are describing. Thanks
/testenv up |
@geido Ephemeral environment spinning up at http://34.221.86.174:8080. Credentials are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Ephemeral environment shutdown and build artifacts deleted. |
SUMMARY
Fixes an issue for which the default temporal column wasn't picked up correctly
BEFORE
188827803-5e994ce4-0413-4e74-a22c-d9221934c378.mov
AFTER
DEV.Superset.2.mp4
TESTING INSTRUCTIONS
ADDITIONAL INFORMATION