From 30dbc91d6824a41d4ee02b632462df175d6ffe9b Mon Sep 17 00:00:00 2001 From: Timm Fitschen <t.fitschen@indiscale.com> Date: Wed, 10 Feb 2021 15:38:24 +0000 Subject: [PATCH] New functionality for controlling, debugging and testing query caching. --- CHANGELOG.md | 4 ++ src/caosdb/common/models.py | 83 +++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd2bbfd2..8c47ddad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### +* Added `cache` paramter to `execute_query` and `Query.execute` which indicates + whether server may use the cache for the query execution. +* Added `cached` property to the `Query` class which indicates whether the + server used the cache for the execution of the last query. * Versioning support (experimental). The version db.Version class can represents particular entity versions and also the complete history of an entity. diff --git a/src/caosdb/common/models.py b/src/caosdb/common/models.py index d857d5c9..5800e5cc 100644 --- a/src/caosdb/common/models.py +++ b/src/caosdb/common/models.py @@ -3611,6 +3611,23 @@ class ACL(): class Query(): + """Query + + Attributes + ---------- + q : str + The query string. + flags : dict of str + A dictionary of flags to be send with the query request. + messages : _Messages() + A container of messages included in the last query response. + cached : bool + indicates whether the server used the query cache for the execution of + this query. + results : int or Container + The number of results (when this was a count query) or the container + with the resulting entities. + """ def putFlag(self, key, value=None): self.flags[key] = value @@ -3626,10 +3643,12 @@ class Query(): def __init__(self, q): self.flags = dict() self.messages = _Messages() + self.cached = None if isinstance(q, etree._Element): self.q = q.get("string") self.results = int(q.get("results")) + self.cached = q.get("cached").lower() == "true" for m in q: if m.tag.lower() == 'warning' or m.tag.lower() == 'error': @@ -3637,17 +3656,43 @@ class Query(): else: self.q = q - def execute(self, unique=False, raise_exception_on_error=True, - **kwargs): + def execute(self, unique=False, raise_exception_on_error=True, cache=True): + """Execute a query (via a server-requests) and return the results. + + Parameters + ---------- + + unique : bool + Whether the query is expected to have only one entity as result. + Defaults to False. + raise_exception_on_error : bool + Whether an exception should be raises when there are errors in the + resulting entities. Defaults to True. + cache : bool + Whether to use the query cache (equivalent to adding a "cache" + flag) to the Query object. Defaults to True. + + Returns + ------- + results : Container or integer + Returns an integer when it was a `COUNT` query. Otherwise, returns a + Container with the resulting entities. + """ connection = get_connection() - query_dict = dict(self.flags) + + flags = self.flags + if cache is False: + flags["cache"] = "false" + query_dict = dict(flags) query_dict["query"] = str(self.q) + _log_request("GET Entity?" + str(query_dict), None) http_response = connection.retrieve( entity_uri_segments=["Entity"], - query_dict=query_dict, **kwargs) + query_dict=query_dict) cresp = Container._response_to_entities(http_response) self.results = cresp.query.results + self.cached = cresp.query.cached if self.q.lower().startswith('count') and len(cresp) == 0: # this was a count query @@ -3672,8 +3717,32 @@ class Query(): return cresp -def execute_query(q, unique=False, raise_exception_on_error=True, flags=None, - **kwargs): +def execute_query(q, unique=False, raise_exception_on_error=True, cache=True, flags=None): + """Execute a query (via a server-requests) and return the results. + + Parameters + ---------- + + q : str + The query string. + unique : bool + Whether the query is expected to have only one entity as result. + Defaults to False. + raise_exception_on_error : bool + Whether an exception should be raises when there are errors in the + resulting entities. Defaults to True. + cache : bool + Whether to use the query cache (equivalent to adding a "cache" flag). + Defaults to True. + flags : dict of str + Flags to be added to the request. + + Returns + ------- + results : Container or integer + Returns an integer when it was a `COUNT` query. Otherwise, returns a + Container with the resulting entities. + """ query = Query(q) if flags is not None: @@ -3681,7 +3750,7 @@ def execute_query(q, unique=False, raise_exception_on_error=True, flags=None, return query.execute(unique=unique, raise_exception_on_error=raise_exception_on_error, - **kwargs) + cache=cache) class DropOffBox(list): -- GitLab