httk.store.db ============= .. py:module:: httk.store.db .. autoapi-nested-parse:: The SQL storage layer of httk-store: store frozen dataclasses in relational databases. This subpackage turns plain frozen dataclasses — declared storable with the stdlib-only marker vocabulary in httk-core (``Indexed``, ``Unique``, ``Skip``, ``Shape``, ``StorageInfo``, ``stored_property``) — into relational storage. The pure-Python foundation lives here: - :mod:`httk.store.db.schema` — :func:`resolve_schema` reads a storable class into a :class:`~httk.store.db.schema.TableSchema`, the single source of truth for DDL, inserts, selects, and reconstruction; - :mod:`httk.store.db.codecs` — the :class:`ValueCodec` registry with exact, round-trippable encodings for rationals, surds, and datetimes; - :mod:`httk.core.storage` — ``canonical_form`` and ``content_id``, the content identity used for deduplication. These modules import cleanly without sqlalchemy. The SQL layer proper builds on them and requires the ``httk-store[db]`` extra (sqlalchemy): - :class:`~httk.store.db.engine.Database` — the engine wrapper naming where data lives (``Database.sqlite(...)``, ``Database.duckdb(...)``, or the Keeper-backed ``Database.clickhouse(...)``); - :class:`~httk.store.db.store.SqlStore` — save/fetch/dedup/transactions for storable instances, on top of the schema-to-table mapping in :mod:`httk.store.db.mapping`; - :class:`~httk.store.db.searcher.SqlSearcher` (from :meth:`~httk.store.db.store.SqlStore.searcher`) — the query DSL implementing the :mod:`httk.store.query` search protocols, with :class:`~httk.store.db.searcher.SqlVariable`, :class:`~httk.store.db.searcher.SqlColumn` and :class:`~httk.store.db.searcher.SqlExpression`; - :class:`~httk.store.db.entry_provider.StoreEntryProvider` — the bridge that serves stored classes through the neutral :class:`~httk.core.EntryProvider` contract (e.g. as an OPTIMADE API via *httk-serve*); - :func:`~httk.store.db.optimade.optimade_filter_searcher` — OPTIMADE-filter querying over storable classes, tying the generic filter translation in :mod:`httk.store.query.optimade_filters` to the SQL layer. The sqlalchemy-backed names are imported lazily on first attribute access, so ``import httk.store.db`` keeps working without sqlalchemy; touching them without sqlalchemy installed raises :class:`ImportError` naming the extra. Submodules ---------- .. toctree:: :maxdepth: 1 /reference/autoapi/httk/store/db/bulk/index /reference/autoapi/httk/store/db/bulk_deferred/index /reference/autoapi/httk/store/db/bulk_parallel/index /reference/autoapi/httk/store/db/clickhouse/index /reference/autoapi/httk/store/db/codecs/index /reference/autoapi/httk/store/db/engine/index /reference/autoapi/httk/store/db/entry_provider/index /reference/autoapi/httk/store/db/fsck/index /reference/autoapi/httk/store/db/graph/index /reference/autoapi/httk/store/db/layout/index /reference/autoapi/httk/store/db/mapping/index /reference/autoapi/httk/store/db/optimade/index /reference/autoapi/httk/store/db/paging/index /reference/autoapi/httk/store/db/results/index /reference/autoapi/httk/store/db/rows/index /reference/autoapi/httk/store/db/schema/index /reference/autoapi/httk/store/db/searcher/index /reference/autoapi/httk/store/db/store/index /reference/autoapi/httk/store/db/stored_federation/index /reference/autoapi/httk/store/db/stored_properties/index Exceptions ---------- .. autoapisummary:: httk.store.db.MultipleResultsError httk.store.db.NoResultError httk.store.db.SchemaError Classes ------- .. autoapisummary:: httk.store.db.ResultRow httk.store.db.ValueCodec Functions --------- .. autoapisummary:: httk.store.db.register_value_codec httk.store.db.register_schema_override httk.store.db.resolve_schema Package Contents ---------------- .. 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:: 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:: ValueCodec An exact encoding of one Python value type across one or more scalar columns. The ``columns`` tuple gives ``(suffix, kind)`` pairs: the empty suffix names the field's own column (by convention the query column), non-empty suffixes are appended to the field name by the schema layer (e.g. ``"_exact"``). ``encode`` and ``decode`` map a value to and from the column-value tuple, in ``columns`` order, and must round-trip exactly. :param name: The registry name of the codec. :param python_type: The Python type stored by the codec. :param columns: The column suffix and scalar-kind pairs encoded by the codec. :param encode: The function that encodes a value into column values. :param decode: The function that reconstructs a value from column values. :param query_suffix: The suffix of the query and index column. .. py:attribute:: name :type: str Registry name of the codec (e.g. ``"fraction"``). .. py:attribute:: python_type :type: type The Python type this codec stores; matched exactly first, then by subclass. .. py:attribute:: columns :type: tuple[tuple[str, httk.store.db.codecs.ScalarKind], ...] The ``(column name suffix, scalar kind)`` pairs the codec encodes into. .. py:attribute:: encode :type: collections.abc.Callable[[Any], tuple[Any, Ellipsis]] Encode a value into one scalar per entry of ``columns``, in order. .. py:attribute:: decode :type: collections.abc.Callable[[tuple[Any, Ellipsis]], Any] Recover the exact value from the tuple produced by ``encode``. .. py:attribute:: query_suffix :type: str :value: '' Suffix of the column used for querying/indexing (normally the empty suffix). .. py:function:: register_value_codec(codec) Register ``codec`` in the value-codec registry. :param codec: The codec to register. :return: None. :raises ValueError: If the codec name or Python type is already registered. .. py:exception:: SchemaError Bases: :py:obj:`Exception` A class or field cannot be resolved into a storage schema; the message names both. .. py:function:: register_schema_override(cls, info) Register an external :class:`~httk.core.storage.StorageInfo` for a class that cannot declare one. The registered info is used by :func:`resolve_schema` whenever no explicit ``override`` argument is passed, and takes precedence over a ``__httk_storage__`` declaration on the class itself. :param cls: The storable class whose schema should be overridden. :param info: The external storage information to register. :return: None. .. py:function:: resolve_schema(cls, *, override = None) Resolve (and cache) the :class:`~httk.store.db.schema.TableSchema` of a storable dataclass. The effective :class:`~httk.core.storage.StorageInfo` is, in order of precedence: the explicit ``override`` argument, an info registered via :func:`register_schema_override`, the class's own ``__httk_storage__`` attribute, or defaults. Results are cached per ``(class, effective override)``, so repeated calls return the same :class:`~httk.store.db.schema.TableSchema` object. Reference cycles (a class referencing itself, or mutually referencing classes) are allowed and resolve without recursion loops. :param cls: The storable class to resolve. :param override: External storage information taking precedence over declarations. :return: The cached resolved table schema. :raises httk.store.db.schema.SchemaError: If the class is not a frozen dataclass or one of its fields cannot be resolved; the diagnostic names the class and field.