Skip to content
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

feat: Support multiple queries per request #11880

Merged
merged 21 commits into from
Dec 18, 2020

Conversation

simcha90
Copy link
Contributor

@simcha90 simcha90 commented Dec 1, 2020

SUMMARY

This feat give opportunity to get from BE response multiple query results and pass them to Chart plugins

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Network Response:

Screen Shot 2020-12-01 at 20 27 41

Results in chart plugin before:
Screen Shot 2020-12-01 at 20 26 26

Results in chart plugin after:
Screen Shot 2020-12-01 at 20 26 06

TEST PLAN

Build request with multiple queries
Related to: apache-superset/superset-ui#846

ADDITIONAL INFORMATION

  • Has associated issue:
  • Changes UI
  • Requires DB Migration.
  • Confirm DB Migration upgrade and downgrade tested.
  • Introduces new feature or API
  • Removes existing feature or API

Copy link
Member

@amitmiran137 amitmiran137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

look stright forward
extending the object and keeping backward comparability to a single query response

@codecov-io
Copy link

codecov-io commented Dec 1, 2020

Codecov Report

Merging #11880 (197ba55) into master (b592cc7) will increase coverage by 0.23%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #11880      +/-   ##
==========================================
+ Coverage   63.37%   63.60%   +0.23%     
==========================================
  Files         970      481     -489     
  Lines       47937    29682   -18255     
  Branches     4736        0    -4736     
==========================================
- Hits        30380    18880   -11500     
+ Misses      17370    10802    -6568     
+ Partials      187        0     -187     
Flag Coverage Δ
javascript ?
python 63.60% <ø> (-0.55%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
superset/db_engines/hive.py 0.00% <0.00%> (-85.72%) ⬇️
superset/db_engine_specs/hive.py 54.61% <0.00%> (-29.62%) ⬇️
superset/db_engine_specs/presto.py 69.95% <0.00%> (-12.45%) ⬇️
superset/examples/world_bank.py 97.10% <0.00%> (-2.90%) ⬇️
superset/examples/birth_names.py 96.51% <0.00%> (-2.33%) ⬇️
superset/views/database/mixins.py 80.70% <0.00%> (-1.76%) ⬇️
superset/models/core.py 88.07% <0.00%> (-0.82%) ⬇️
superset/connectors/sqla/models.py 91.37% <0.00%> (-0.14%) ⬇️
superset/views/core.py 75.37% <0.00%> (-0.08%) ⬇️
...rontend/src/components/ListView/CardSortSelect.tsx
... and 475 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b592cc7...d6ffbf2. Read the comment docs.

@robdiciuccio
Copy link
Member

@simchanielsen there's currently a PR open implementing async queries for charts (SIP-39) that I'm hoping to get merged in the next week or so. I'm curious how you see multiple queries working with this async model, and what changes you're proposing on the backend to support this.

Also curious, in general, what the use cases are for multiple queries in a visualization.

@amitmiran137
Copy link
Member

@robdiciuccio A classic use-case for multiple queries is uplifting table pagination in which you query the page data and second the total item count for determining how many pages to display

@amitmiran137
Copy link
Member

And about async queries, once feature is mature we can consider supporting multiple queries there as well
But for now we not familiar with that feature

@villebro
Copy link
Member

villebro commented Dec 2, 2020

@robdiciuccio based on my latest review of the async PR, I don't anticipate this feature will cause any complications with said feature.

Copy link
Member

@villebro villebro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on first pass, but I'd be interested in seeing what the cached status looks like. I assume it should be like this:

  • If all queries missed the cache, no cache pill is visible.
  • If at least one result came from the cache, the cache pill is visible.
  • On hover the cache status of all queries should be visible?
    Curious to hear your thoughts.

Comment on lines 174 to 185
const cachedWhen = moment.utc(cachedDttm).fromNow();
const cachedWhen = cachedDttm.map(itemCachedDttm =>
moment.utc(itemCachedDttm).fromNow(),
);
const updatedWhen = updatedDttm ? moment.utc(updatedDttm).fromNow() : '';
const refreshTooltip = isCached
? t('Cached %s', cachedWhen)
: (updatedWhen && t('Fetched %s', updatedWhen)) || '';
const getCachedTitle = itemCached => {
return itemCached
? t('Cached %s', cachedWhen)
: updatedWhen && t('Fetched %s', updatedWhen);
};
let refreshTooltip = isCached.map(getCachedTitle) || '';
// If all queries have same cache time we can unit them to one
refreshTooltip = [...new Set(refreshTooltip)].join(', ');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you share a screenshot of what this looks like?

Copy link
Contributor Author

@simcha90 simcha90 Dec 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@villebro So basically if all requests will have same time it will look like"
Screen Shot 2020-12-02 at 15 04 00
And if different then like this (just emulate by code changes for screenshot):
Screen Shot 2020-12-02 at 15 05 37

Copy link
Member

@villebro villebro Dec 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should instead have something like this for the case when there are more than one result:

Force refresh
Query 1: Fetched a minute ago
Query 2: Fetched 3 minutes ago
Query 3: Not cached

Also, we should think about how to display multiple results in the "View Results" tab. But that can wait; let's just make sure the user experience is unchanged for single queries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@simchanielsen
could you share the new screenshot?

Copy link
Contributor Author

@simcha90 simcha90 Dec 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

It's only emulation of 2 queries, by code changes, in real case:

  1. if all queries have same cache time they will be squashed to one notification like it was before my change
  2. if queries will have different time it will be shown like here

Copy link
Member

@villebro villebro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. As this feature requires superset-ui/core: "^0.15.15", it won't yet function without the bump. So you may potentially want to wait for the dashboard native filter to merge which should happen shortly (it bumps all relevant deps). If this is urgent, feel free to add the bump to this PR.

@robdiciuccio
Copy link
Member

What's still unclear to me are the proposed backend changes to support multiple queries, and how that will affect the async query feature, which will be coming out of draft status this week.

  • Which endpoints will support multiple queries? /api/v1/chart/data? /superset/explore_json?
  • What changes will be made in QueryContext and viz.py to support this?

@robdiciuccio
Copy link
Member

Is there a SIP that references support for multiple queries in charts?

@amitmiran137
Copy link
Member

@robdiciuccio BE already supports running multiple queries for a long time now.
The what handling the multiple responses properly in the FE

@villebro
Copy link
Member

villebro commented Dec 2, 2020

@robdiciuccio here's my take on the topic:

  • The multiple queries feature was added prior to the SIP process, but was only implemented on the backend - the necessary frontend changes weren't done.

  • The api/v1/chart/data already supports multiple queries, so no backend changes are necessary.

  • superset/explore_json and viz.py don't need to be changed, as they won't be supporting multiple queries.

  • Based on my understanding of the async PR, QueryContext gets a cache_key of it's own in QueryContext.cache_key(), and that can handle multiple queries. I'm uncertain if we want to cache only the QueryObject or both the QueryObject and QueryContext going forward, but both can be done.

  • There are a few things that still need to be addressed. For instance, the "View Results" and "View Query" features currently only support showing the query/results for a single query object. But AFAIK this isn't a major problem and can be addressed later. It would be great to get design input on these at some point.

@robdiciuccio
Copy link
Member

Thanks for the context @villebro. Good to know the plan is not to modify the backend here.

const isFaded = refreshOverlayVisible && !errorMessage;
this.renderContainerStartTime = Logger.getTimestamp();
if (chartStatus === 'failed') {
return this.renderErrorMessage();
return queriesResponse.map(item => this.renderErrorMessage(item));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a screenshot of multiple errors rendered in a chart?

Copy link
Contributor Author

@simcha90 simcha90 Dec 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robdiciuccio Hi good catch, I didn't check it properly for all kinds of charts (new/old). I pushed now some small fix for it. Basically for now for new api there is no case that it returns more than 1 error per request even for multi queries, but if it will return we can support it, but for now it will be only one error.

P.S. If you have some more places where I can check this functionality, update me please, because I'm new in Superset so I don't know all places and cases of its usages :)

Attaching screenshots after my fix for charts:

  1. Old charts:
    Screen Shot 2020-12-03 at 9 02 11

  2. New charts:
    Screen Shot 2020-12-03 at 9 10 54

  3. New charts with multiqueries (looks the same):
    Screen Shot 2020-12-03 at 9 00 19

),
);
return dispatch(
chartUpdateSucceeded(queryResponse, queriesResponse, key),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the thinking behind adding another value here rather than replacing the current queryResponse? This is essentially doubling the data that's being passed around to components.

Copy link
Contributor Author

@simcha90 simcha90 Dec 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robdiciuccio hmm... good point, actually I wanted avoid refactoring of a lot places in code, but now I see I think I can handle it, I also will add someone more to review, where I see that my refactor will affect his parts of code to be sure.

I pushed now refactored code as you proposed and asked @etr2460 to review also... I tested these changes in explore/dashboard in areas that I know, but if there are some other places, that I need to test please update me.

I also see that affected some code that @suddjian implemented, may be it can be good to add him as reviewer?

Thanks

@simcha90
Copy link
Contributor Author

simcha90 commented Dec 3, 2020

LGTM. As this feature requires superset-ui/core: "^0.15.15", it won't yet function without the bump. So you may potentially want to wait for the dashboard native filter to merge which should happen shortly (it bumps all relevant deps). If this is urgent, feel free to add the bump to this PR.

It's backward compatible feature so can be merged unrelated superset-ui

@simcha90 simcha90 changed the title feat: Support multiple queries per request WIP: feat: Support multiple queries per request Dec 3, 2020
@@ -132,12 +132,12 @@ export const selectIndicatorsForChart = (
// for now we only need to know which columns are compatible/incompatible,
// so grab the columns from the applied/rejected filters
const appliedColumns: Set<string> = new Set(
(chart?.queryResponse?.applied_filters || []).map(
(chart?.queriesResponse?.[0]?.applied_filters || []).map(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@etr2460 Hi I see you implemented this part of code, I refactored it to use multi queries, can you please look that my changes not break some functionality. Thanks

Copy link
Member

@suddjian suddjian Dec 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented this logic. The goal of these two lines is to get a set of all the filters that were applied on a chart, and the filters that were rejected (due to the column not existing in the dataset), in order to display them in the filter badge.

If a chart makes multiple queries, it would probably be more correct to add the applied_filters and rejected_filters from each of the queries, instead of just the first one. But that really depends on how dashboard filters works with multiple queries.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a chart makes multiple queries, it would probably be more correct to add the applied_filters and rejected_filters from each of the queries, instead of just the first one. But that really depends on how dashboard filters works with multiple queries.

I think we should probably be applying the same filters to all QueryObjects. Since a QueryContext currently only supports a single datasource, the applied/rejected columns should be identical. However, temporal filters will only be applicable for QueryObjects with is_temporal: true.

chartStackTrace: action.queryResponse
? action.queryResponse.stacktrace
queriesResponse: action.queriesResponse,
chartStackTrace: action.queriesResponse
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@etr2460 and also this one please

@simcha90 simcha90 changed the title WIP: feat: Support multiple queries per request feat: Support multiple queries per request Dec 3, 2020
Copy link
Member

@etr2460 etr2460 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the error message changes are fine

@amitmiran137
Copy link
Member

Can this be merged?
or those wait for additional review?

@robdiciuccio
Copy link
Member

Hi @simchanielsen, heads-up that the async queries PR has been merged, which may affect how the chart actions are called here. Happy to answer any questions about the changes.

@@ -361,38 +361,36 @@ export function exploreJSON(

const chartDataRequestCaught = chartDataRequest
.then(response => {
const queriesResponse = response.result;

if (isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) {
// deal with getChartDataRequest transforming the response data
const result = 'result' in response ? response.result[0] : response;
return dispatch(chartUpdateQueued(result, key));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robdiciuccio should we continue sending a single result to chartUpdateQuered action?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the return value here is a async job metadata payload.

@amitmiran137
Copy link
Member

Can we review and merge ?

@robdiciuccio
Copy link
Member

Running this locally with the GLOBAL_ASYNC_QUERIES feature flag enabled results in the following error when rendering a dashboard:

TypeError: Cannot read property 'call' of undefined
    at Chart.render (Chart.jsx?484f:272)

Also:

Warning: Failed prop type: Invalid prop `charts.597.queriesResponse` of type `object` supplied to `Dashboard`, expected an array.
Warning: Failed prop type: Invalid prop `chart.queriesResponse` of type `object` supplied to `Chart`, expected an array.

Looking into the cause.

@robdiciuccio
Copy link
Member

Here are the changes necessary. Let me know if you'd like me to commit them to the PR.

Screen Shot 2020-12-17 at 5 27 20 PM

amitmiran137 added 5 commits December 18, 2020 07:31
* upstream/master: (55 commits)
  feat(explore): time picker enhancement (apache#11418)
  feat: update alert/report icons and column order (apache#12081)
  feat(explore): metrics and filters controls redesign (apache#12095)
  feat(alerts/reports): add refresh action (apache#12071)
  chore: add latest tag action (apache#11148)
  fix(reports): increase crontab size and alert fixes (apache#12056)
  Small typo fix in Athena connection docs (apache#12099)
  feat(queries): security perm simplification (apache#12072)
  feat(databases): security perm simplification (apache#12036)
  feat(dashboards): security permissions simplification (apache#12012)
  feat(logs): security permissions simplification (apache#12061)
  chore: Remove unused CodeModal (apache#11972)
  Fix typescript error (apache#12074)
  fix: handle context-dependent feature flags in CLI (apache#12088)
  fix: Fix "View in SQLLab" bug (apache#12086)
  feat(alert/report): add 'not null' condition option to modal (apache#12077)
  bumping superset ui to 15.18 and deckgl to 0.3.2 (apache#12078)
  fix: Python dependencies in apache#11499 (apache#12079)
  reset active tab on open (apache#12048)
  fix: improve import flow UI/UX (apache#12070)
  ...
@amitmiran137
Copy link
Member

@robdiciuccio I've added necessary changes.
could anyone rerun the E2E?

@villebro
Copy link
Member

@amitmiran137 CI has been slightly flaky lately. I restarted, let's see if this fixes it.

@robdiciuccio robdiciuccio merged commit 49ec13c into apache:master Dec 18, 2020
villebro pushed a commit to preset-io/superset that referenced this pull request Jan 7, 2021
* refactor: add queriesData fields for multiple queries

* feat: support multi queries request

* lint: fix lint

* lint: fix lint

* lint: fix lint

* fix: fix CR notes

* fix: fix CR notes

* fix: fix CR notes

* fix: fix error case for multi queries

* feat: change queryResponse to queriesResponse

* fix: revert webpack

* test: fix tests

* chore: lint

* chore: adjust asyncEvent to multiple results

* fix: lint

* fix: eslint

* fix: another eslint rule

Co-authored-by: Amit Miran <[email protected]>
Co-authored-by: amitmiran137 <[email protected]>
villebro pushed a commit to preset-io/superset that referenced this pull request Jan 7, 2021
* refactor: add queriesData fields for multiple queries

* feat: support multi queries request

* lint: fix lint

* lint: fix lint

* lint: fix lint

* fix: fix CR notes

* fix: fix CR notes

* fix: fix CR notes

* fix: fix error case for multi queries

* feat: change queryResponse to queriesResponse

* fix: revert webpack

* test: fix tests

* chore: lint

* chore: adjust asyncEvent to multiple results

* fix: lint

* fix: eslint

* fix: another eslint rule

Co-authored-by: Amit Miran <[email protected]>
Co-authored-by: amitmiran137 <[email protected]>
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.0.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels size/L 🚢 1.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants