httk.store.query ================ .. py:module:: httk.store.query .. autoapi-nested-parse:: Define backend-agnostic query protocols and portable query capabilities. The :mod:`httk.store.query.optimade_filters` module contains OPTIMADE filter-translation machinery for serving layers and is intentionally not lifted here. Submodules ---------- .. toctree:: :maxdepth: 1 /reference/autoapi/httk/store/query/optimade_filters/index /reference/autoapi/httk/store/query/paging_tokens/index /reference/autoapi/httk/store/query/portable/index /reference/autoapi/httk/store/query/protocols/index Attributes ---------- .. autoapisummary:: httk.store.query.ID_FIELD Exceptions ---------- .. autoapisummary:: httk.store.query.CountUnavailableError httk.store.query.MultipleResultsError httk.store.query.NoResultError httk.store.query.PaginationCursorError httk.store.query.UnsupportedQueryError Classes ------- .. autoapisummary:: httk.store.query.PortableQueryCapabilities httk.store.query.ContinuationToken httk.store.query.PageOrder httk.store.query.PageableResultSetLike httk.store.query.ResultPage httk.store.query.ResultRow httk.store.query.ResultRowLike httk.store.query.ResultSetLike httk.store.query.SearchExpression httk.store.query.SearchField httk.store.query.SearchResult httk.store.query.SearchVariable httk.store.query.Searcher httk.store.query.Store Functions --------- .. autoapisummary:: httk.store.query.portable_query_capabilities httk.store.query.portable_query_fields Package Contents ---------------- .. py:class:: PortableQueryCapabilities Describe the query operations guaranteed by one property definition. ``query-support`` expresses a cross-provider guarantee, not a particular server's implementation detail. ``all optional`` is deliberately fail-closed here: it gives a portable client no operation it can rely on. A server may offer more, but that is not represented by the definition. :param query_support: The normalized declared query-support level. :param operations: The portable operation families guaranteed by the definition. .. py:attribute:: query_support :type: str | None .. py:attribute:: operations :type: frozenset[str] .. py:method:: supports(operation) Report whether ``operation`` is guaranteed by this definition. :param operation: The operation family to test. :return: ``True`` when the operation is portable. .. py:function:: portable_query_capabilities(definition) Derive the portable operation subset for ``definition``. The operation names are ``"equality"``, ``"ordering"``, ``"stringmatching"``, and ``"set"``. They intentionally describe the query-language operation families rather than storage implementation. ``IS [NOT] KNOWN`` is part of the equality family because it is the NULL spelling of equality/inequality in the OPTIMADE filter language. :param definition: The OPTIMADE property definition to inspect. :return: The guaranteed portable query capabilities. .. py:function:: portable_query_fields(entry_type, *, include = (), exclude = ()) Return the ordered portable query fields described by ``entry_type``. By default, this selects scalar fields and flat lists with at least one operation guaranteed by their definition. ``include`` is an explicit binding override for named existing properties; it is appended as a second ordered group after the derived fields, in entry-definition order among the included names, but does not manufacture query capabilities absent from that definition. ``exclude`` always wins. Both arguments reject unknown or duplicate names so binding mistakes cannot silently broaden a profile. :param entry_type: The entry definition whose properties are inspected. :param include: Existing property names to append to the derived selection. :param exclude: Existing property names to remove from the selection. :return: Derived property names followed by explicitly included names. :raises ValueError: If ``include`` or ``exclude`` contains an unknown or duplicate property name. .. py:data:: ID_FIELD :type: Final :value: '__id' The backend field name used for the served entry identifier. .. py:class:: ContinuationToken Bases: :py:obj:`str` Carry an opaque URL-safe continuation value. It is a ``str`` subclass so normal JSON serializers preserve it as a scalar value. Applications should pass a token returned by a page back unchanged; data backends validate its version, structure, and result-plan fingerprint before using any decoded value as a bound parameter. :param value: The opaque continuation value. .. py:exception:: CountUnavailableError Bases: :py:obj:`RuntimeError` Report that a store cannot provide an exact query count. .. py:exception:: MultipleResultsError Bases: :py:obj:`LookupError` Report that a result-set ``one()`` operation found multiple results. .. py:exception:: NoResultError Bases: :py:obj:`LookupError` Report that a result-set ``one()`` operation found no matching result. .. py:class:: PageOrder Order a continuation page by one named scalar result projection. ``name`` identifies the name supplied to ``results()`` (or :meth:`Searcher.output`), never a backend column object. The result-set implementation validates that it is a root scalar projection before it generates SQL. :param name: The declared scalar output name used for ordering. :param descending: Whether to order this field in descending order. :param nulls: Whether null values sort first or last. .. py:attribute:: name :type: str .. py:attribute:: descending :type: bool :value: False .. py:attribute:: nulls :type: Literal['first', 'last'] :value: 'last' .. py:class:: PageableResultSetLike Bases: :py:obj:`Protocol` Expose optional continuation-page capability on a frozen result set. This deliberately extends neither :class:`ResultSetLike` nor :class:`Searcher`: stores that do not support seek pagination remain fully conforming to the required portable contracts. .. py:method:: page(*, size, order_by, cursor = None, include_total = False) Return one ordered continuation page. .. py:exception:: PaginationCursorError Bases: :py:obj:`ValueError` Report that a continuation cursor is malformed, expired, or belongs to another result plan. .. py:class:: ResultPage Represent an immutable continuation-page result. ``rows`` is always a tuple. Returned rows are ordinary persistent result rows, not the expiring proxies produced by ``SqlResultSet.cursor()``. ``total`` is populated only when the caller explicitly asks for it. :param rows: The persistent rows returned by the page. :param next: The token for the next page, if one exists. :param previous: The token for the previous page, if one exists. :param total: The exact result count when requested, otherwise ``None``. .. py:attribute:: rows :type: tuple[ResultRowLike, Ellipsis] .. py:attribute:: next :type: ContinuationToken | None .. py:attribute:: previous :type: ContinuationToken | None .. py:attribute:: total :type: int | None :value: None .. py:class:: ResultRow(values, names, resolver = None, guard = None) Represent one named result row by position, name, or attribute. :param values: The row values in declaration order. :param names: The corresponding output names. :param resolver: An optional lazy value resolver. :param guard: An optional callback that rejects access to expired values. .. py:property:: names :type: tuple[str, Ellipsis] Return the declared output names. .. py:property:: values :type: tuple[Any, Ellipsis] Return the row values in declaration order. .. py:class:: ResultRowLike Bases: :py:obj:`Protocol` Require named access to one result row. .. py:property:: names :type: tuple[str, Ellipsis] Return the row's declared output names. .. py:class:: ResultSetLike Bases: :py:obj:`Protocol` Require the common operations of a materialized result set. .. py:method:: first() Return the first row, or ``None`` when no row matches. .. py:method:: one() Return the only row, or raise when the count is not one. .. py:method:: scalars(name = None) Iterate over one named scalar output. .. py:class:: SearchExpression Bases: :py:obj:`Protocol` Require composable backend search expressions. .. py:class:: SearchField Bases: :py:obj:`Protocol` Expose a queryable field of a search variable. In addition to the methods below, fields support the rich comparison operators (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), returning :class:`SearchExpression`. The handlers invoke those via ``getattr(field, '__eq__')(value)`` since the comparison dunders cannot be typed as expression-returning. The three string-matching methods take **literal** text: no wildcard or pattern syntax whatsoever crosses this contract, so ``%`` and ``_`` (and any other metacharacter) match themselves. A backend is therefore free to implement them with SQL ``LIKE`` over an escaped pattern, with a regular expression, or with a full-text index — the choice is invisible here. .. py:method:: has(value) Match a list field containing ``value``. .. py:method:: has_any(*values) Match a list field containing any of ``values``. .. py:method:: has_only(*values) Match a list field containing no values outside ``values``. .. py:method:: is_in(*values) Match a root scalar field whose value is one of ``values``. ``None`` is an explicit member: it matches a null field value, and its negation excludes nulls rather than inheriting SQL's three-valued ``NOT IN (..., NULL)`` behavior. Backends define the corresponding semantics for child or set fields; for example, a backend may use the existing ``has_only``-style all-values reading for a child field. .. py:method:: contains(text) Match values containing ``text`` as a literal substring. .. py:method:: startswith(prefix) Match values beginning with the literal ``prefix``. .. py:method:: endswith(suffix) Match values ending with the literal ``suffix``. .. py:class:: SearchResult Bases: :py:obj:`NamedTuple` Represent one match with declared output values and names. ``values`` holds one entry per :meth:`Searcher.output` call in declaration order; it is a tuple, so ``values, names = result`` and ``result[0][0]`` both work. .. py:attribute:: values :type: tuple[Any, Ellipsis] .. py:attribute:: names :type: tuple[str, Ellipsis] .. py:class:: SearchVariable Bases: :py:obj:`Protocol` Bind a query variable to a target type whose attributes yield fields. ``always_true``/``always_false`` are reserved names: they are real methods of the variable, never stored fields resolved through ``__getattr__``. They exist so a translation layer can express a constant truth value without inventing a probe field. A ``field == field`` probe is NULL-unsound, since it yields NULL (not true) for a NULL field. .. py:method:: always_true() An expression that matches every row. .. py:method:: always_false() An expression that matches no row. .. py:class:: Searcher Bases: :py:obj:`Protocol` Build one query and iterate its results. Iteration yields one :class:`SearchResult` per match, so ``item[0][0]`` is the first declared output of the match (typically the matched row object). The expressions received by ``add`` are always ones produced by this same backend's search variables, so implementations may type them as their own expression class; a backend that needs a second (post-filter) evaluation position decides that from the expression itself, not from the caller. .. py:attribute:: offset :type: int .. py:method:: variable(target) Bind a query variable to ``target``. .. py:method:: output(variable, name) Declare ``variable`` as a named result output. .. py:method:: add(expression) Add a filter expression to the query. .. py:method:: count() Return the exact count of the current query. .. py:method:: set_limit(limit) Set the query limit. .. py:method:: add_offset(offset) Add an offset to the query. .. py:method:: add_sort(field, descending) Add a field sort to the query. .. py:method:: results(**outputs) Return a result set for the requested named outputs. .. py:class:: Store Bases: :py:obj:`Protocol` Require a store that can create a query searcher. .. py:method:: searcher() Create an empty searcher. .. py:exception:: UnsupportedQueryError Bases: :py:obj:`ValueError` Report that a valid query operation is outside a store's supported profile.