Update query hash with parameters applied (#6683)

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>
This commit is contained in:
Eric Radman
2024-01-09 22:46:31 -05:00
committed by GitHub
parent 1b1b9bd98d
commit 4d81c3148d
3 changed files with 29 additions and 4 deletions

View File

@@ -40,7 +40,11 @@ from redash.models.base import (
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,
@@ -831,7 +835,20 @@ class Query(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model):
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")

View File

@@ -381,7 +381,7 @@ class TestQueryDropdownsResource(BaseTestCase):
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
@@ -394,7 +394,7 @@ class TestQueryDropdownsResource(BaseTestCase):
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

View File

@@ -466,6 +466,14 @@ class TestQueryAll(BaseTestCase):
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):