From 8fc3dd1b7240bdcf33564eb40a4ca9051998f2b8 Mon Sep 17 00:00:00 2001 From: Jesse Devaney <22608765+JesseSDevaney@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:01:59 -0400 Subject: [PATCH] Fix queries being re-run because of broken parameters comparison (#41659) * fix queries being re-run because parameters were being compared with different sorts * add test to validate and enforce behavior --- ...redundant-queries-on-tab-change.cy.spec.js | 208 +++++++++++++++++- .../dashboard/actions/data-fetching.js | 14 +- 2 files changed, 215 insertions(+), 7 deletions(-) diff --git a/e2e/test/scenarios/dashboard/reproductions/39863-redundant-queries-on-tab-change.cy.spec.js b/e2e/test/scenarios/dashboard/reproductions/39863-redundant-queries-on-tab-change.cy.spec.js index 44b87f62e6a..95bf5ecd159 100644 --- a/e2e/test/scenarios/dashboard/reproductions/39863-redundant-queries-on-tab-change.cy.spec.js +++ b/e2e/test/scenarios/dashboard/reproductions/39863-redundant-queries-on-tab-change.cy.spec.js @@ -14,7 +14,7 @@ const { ORDERS } = SAMPLE_DATABASE; const TAB_1 = { id: 1, name: "Tab 1" }; const TAB_2 = { id: 2, name: "Tab 2" }; -const DATE_FILER = { +const DATE_FILTER = { id: "2", name: "Date filter", slug: "filter-date", @@ -31,7 +31,7 @@ const COMMON_DASHCARD_INFO = { card_id: ORDERS_QUESTION_ID, parameter_mappings: [ { - parameter_id: DATE_FILER.id, + parameter_id: DATE_FILTER.id, card_id: ORDERS_QUESTION_ID, target: ["dimension", CREATED_AT_FIELD_REF], }, @@ -40,6 +40,151 @@ const COMMON_DASHCARD_INFO = { size_y: 4, }; +const ID_FILTER = { + id: "3", + name: "ID filter", + slug: "filter-id", + type: "id", +}; + +const USER_ID_FILTER = { + id: "4", + name: "User ID filter", + slug: "filter-user-id", + type: "id", +}; + +const PRODUCT_ID_FILTER = { + id: "5", + name: "Product ID filter", + slug: "filter-product-id", + type: "id", +}; + +const SUBTOTAL_FILTER = { + id: "6", + name: "Subtotal filter", + slug: "filter-subtotal", + type: "number/<=", +}; + +const TOTAL_FILTER = { + id: "7", + name: "Total filter", + slug: "filter-total", + type: "number/<=", +}; + +const TAX_FILTER = { + id: "8", + name: "Tax filter", + slug: "filter-tax", + type: "number/<=", +}; + +const DISCOUNT_FILTER = { + id: "9", + name: "Discount filter", + slug: "filter-discount", + type: "number/<=", +}; + +const QUANTITY_FILTER = { + id: "10", + name: "Quantity filter", + slug: "filter-quantity", + type: "number/<=", +}; + +const ID_FIELD_REF = ["field", ORDERS.ID, { "base-type": "type/BigInteger" }]; + +const USER_ID_FIELD_REF = [ + "field", + ORDERS.USER_ID, + { "base-type": "type/BigInteger" }, +]; + +const PRODUCT_ID_FIELD_REF = [ + "field", + ORDERS.PRODUCT_ID, + { "base-type": "type/BigInteger" }, +]; + +const SUBTOTAL_FIELD_REF = [ + "field", + ORDERS.SUBTOTAL, + { "base-type": "type/Float" }, +]; + +const TOTAL_FIELD_REF = ["field", ORDERS.TOTAL, { "base-type": "type/Float" }]; + +const TAX_FIELD_REF = ["field", ORDERS.TAX, { "base-type": "type/Float" }]; + +const DISCOUNT_FIELD_REF = [ + "field", + ORDERS.DISCOUNT, + { "base-type": "type/Float" }, +]; + +const QUANTITY_FIELD_REF = [ + "field", + ORDERS.QUANTITY, + { "base-type": "type/Number" }, +]; + +const DASHCARD_WITH_9_FILTERS = { + card_id: ORDERS_QUESTION_ID, + parameter_mappings: [ + { + parameter_id: DATE_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", CREATED_AT_FIELD_REF], + }, + { + parameter_id: ID_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", ID_FIELD_REF], + }, + { + parameter_id: USER_ID_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", USER_ID_FIELD_REF], + }, + { + parameter_id: PRODUCT_ID_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", PRODUCT_ID_FIELD_REF], + }, + { + parameter_id: SUBTOTAL_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", SUBTOTAL_FIELD_REF], + }, + { + parameter_id: TOTAL_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", TOTAL_FIELD_REF], + }, + { + parameter_id: TAX_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", TAX_FIELD_REF], + }, + { + parameter_id: DISCOUNT_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", DISCOUNT_FIELD_REF], + }, + { + parameter_id: QUANTITY_FILTER.id, + card_id: ORDERS_QUESTION_ID, + target: ["dimension", QUANTITY_FIELD_REF], + }, + ], + size_x: 10, + size_y: 4, +}; + describe("issue 39863", () => { beforeEach(() => { restore(); @@ -52,7 +197,7 @@ describe("issue 39863", () => { it("should not rerun queries when switching tabs and there are no parameter changes", () => { createDashboardWithTabs({ tabs: [TAB_1, TAB_2], - parameters: [DATE_FILER], + parameters: [DATE_FILTER], dashcards: [ createMockDashboardCard({ ...COMMON_DASHCARD_INFO, @@ -95,6 +240,63 @@ describe("issue 39863", () => { goToTab(TAB_2.name); cy.get("@dashcardQuery.all").should("have.length", 4); }); + + it("should not rerun queries just because there are 9 or more attached filters to a dash-card", () => { + createDashboardWithTabs({ + tabs: [TAB_1, TAB_2], + parameters: [ + DATE_FILTER, + ID_FILTER, + USER_ID_FILTER, + PRODUCT_ID_FILTER, + SUBTOTAL_FILTER, + TOTAL_FILTER, + TAX_FILTER, + DISCOUNT_FILTER, + QUANTITY_FILTER, + ], + dashcards: [ + createMockDashboardCard({ + ...DASHCARD_WITH_9_FILTERS, + id: -1, + dashboard_tab_id: TAB_1.id, + }), + createMockDashboardCard({ + ...DASHCARD_WITH_9_FILTERS, + id: -2, + dashboard_tab_id: TAB_2.id, + }), + ], + }).then(dashboard => visitDashboard(dashboard.id)); + + // Initial query for 1st tab + cy.get("@dashcardQuery.all").should("have.length", 1); + + // Initial query for 2nd tab + goToTab(TAB_2.name); + cy.wait("@dashcardQuery"); + cy.get("@dashcardQuery.all").should("have.length", 2); + + // No parameters change, no query rerun + goToTab(TAB_1.name); + cy.wait("@dashcardQuery"); + cy.get("@dashcardQuery.all").should("have.length", 2); + + // Rerun 1st tab query with new parameters + setDateFilter(); + cy.wait("@dashcardQuery"); + cy.get("@dashcardQuery.all").should("have.length", 3); + + // Rerun 2nd tab query with new parameters + goToTab(TAB_2.name); + cy.wait("@dashcardQuery"); + cy.get("@dashcardQuery.all").should("have.length", 4); + + // No parameters change, no query rerun + goToTab(TAB_1.name); + goToTab(TAB_2.name); + cy.get("@dashcardQuery.all").should("have.length", 4); + }); }); function setDateFilter() { diff --git a/frontend/src/metabase/dashboard/actions/data-fetching.js b/frontend/src/metabase/dashboard/actions/data-fetching.js index 08a51a09f70..7054366686c 100644 --- a/frontend/src/metabase/dashboard/actions/data-fetching.js +++ b/frontend/src/metabase/dashboard/actions/data-fetching.js @@ -622,9 +622,15 @@ function getDatasetQueryParams(datasetQuery = {}) { type, query, native, - parameters: parameters.map(parameter => ({ - ...parameter, - value: parameter.value ?? null, - })), + parameters: parameters + .map(parameter => ({ + ...parameter, + value: parameter.value ?? null, + })) + .sort(sortById), }; } + +function sortById(a, b) { + return a.id.localeCompare(b.id); +} -- GitLab