Skip to content

Commit

Permalink
Update query hash with parameters applied (#6683)
Browse files Browse the repository at this point in the history
This allows queries with parameters to run on a schedule since the hash
used to update the query_result will match.

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Guido Petri <18634426+guidopetri@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 10, 2024
1 parent 1b1b9bd commit 4d81c31
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
21 changes: 19 additions & 2 deletions redash/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
from redash.models.changes import Change, ChangeTrackingMixin # noqa
from redash.models.mixins import BelongsToOrgMixin, TimestampMixin
from redash.models.organizations import Organization
from redash.models.parameterized_query import ParameterizedQuery
from redash.models.parameterized_query import (
InvalidParameterError,
ParameterizedQuery,
QueryDetachedFromDataSourceError,
)
from redash.models.types import (
Configuration,
EncryptedConfiguration,
Expand Down Expand Up @@ -831,7 +835,20 @@ def dashboard_api_keys(self):
def update_query_hash(self):
should_apply_auto_limit = self.options.get("apply_auto_limit", False) if self.options else False
query_runner = self.data_source.query_runner if self.data_source else BaseQueryRunner({})
self.query_hash = query_runner.gen_query_hash(self.query_text, should_apply_auto_limit)
query_text = self.query_text

parameters_dict = {p["name"]: p.get("value") for p in self.parameters} if self.options else {}
if any(parameters_dict):
try:
query_text = self.parameterized.apply(parameters_dict).query
except InvalidParameterError as e:
logging.info(f"Unable to update hash for query {self.id} because of invalid parameters: {str(e)}")
except QueryDetachedFromDataSourceError as e:
logging.info(
f"Unable to update hash for query {self.id} because of dropdown query {e.query_id} is unattached from datasource"
)

self.query_hash = query_runner.gen_query_hash(query_text, should_apply_auto_limit)


@listens_for(Query, "before_insert")
Expand Down
4 changes: 2 additions & 2 deletions tests/handlers/test_query_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def test_allows_access_if_associated_and_has_access_to_parent(self):
query_result = self.factory.create_query_result(data=json_dumps(data))
dropdown_query = self.factory.create_query(latest_query_data=query_result)

options = {"parameters": [{"type": "query", "queryId": dropdown_query.id}]}
options = {"parameters": [{"name": "param", "type": "query", "queryId": dropdown_query.id}]}
query = self.factory.create_query(options=options)

# dropdown_query has been associated with query
Expand All @@ -394,7 +394,7 @@ def test_allows_access_if_associated_and_has_access_to_parent(self):
def test_prevents_access_if_associated_and_doesnt_have_access_to_parent(self):
ds2 = self.factory.create_data_source(group=self.factory.org.admin_group, view_only=False)
dropdown_query = self.factory.create_query(data_source=ds2)
options = {"parameters": [{"type": "query", "queryId": dropdown_query.id}]}
options = {"parameters": [{"name": "param", "type": "query", "queryId": dropdown_query.id}]}
query = self.factory.create_query(data_source=ds2, options=options)

# dropdown_query has been associated with query
Expand Down
8 changes: 8 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,14 @@ def test_update_query_hash_non_basesql(self):
query.update_query_hash()
self.assertEqual(origin_hash, query.query_hash)

def test_update_query_hash_basesql_with_parameters(self):
ds = self.factory.create_data_source(group=self.factory.org.default_group, type="pg")
query = self.factory.create_query(query_text="SELECT {{num}}", data_source=ds)
query.options = {"parameters": [{"type": "number", "name": "num", "value": 5}]}
origin_hash = query.query_hash
query.update_query_hash()
self.assertNotEqual(origin_hash, query.query_hash)


class TestGroup(BaseTestCase):
def test_returns_groups_with_specified_names(self):
Expand Down

0 comments on commit 4d81c31

Please sign in to comment.