Source code for kapps_triplestore_interface.queries.triple_single

# To be imported into ..graph_db.py GraphDB class

from typing import Optional, TYPE_CHECKING
from kapps_triplestore_interface.utils import utils
from kapps_triplestore_interface.utils.iri import IRI
from kapps_triplestore_interface.utils.types import (
    PartialTripleLike,
    SubjectLike,
    PredicateLike,
    ObjectLike,
    GraphNameLike,
    TripleLike,
)
from kapps_triplestore_interface.exceptions import InvalidInputError

from kapps_triplestore_interface.sparql_query import SPARQLQuery

if TYPE_CHECKING:
    from kapps_triplestore_interface import GraphDB


[docs] def triple_exists( self: "GraphDB", triple: TripleLike, named_graph: Optional[GraphNameLike] = None, ) -> bool: """ Check whether a specific triple exists in the graph database. Args: triple (TripleLike): The triple `(subject, predicate, object)` to check. named_graph (Optional[GraphNameLike]): Override the client's default named graph. Returns: bool: True if the triple exists, False otherwise. """ triple = utils.sanitize_triple(triple) named_graph = IRI(named_graph) if named_graph is not None else self.named_graph query = SPARQLQuery.ask( where_clauses=[ utils.triple_to_string(triple, "."), ], named_graph=named_graph, ) result = self.query(query=query) if result is None or result["boolean"] is False: self.logger.debug( f"Unable to find triple ({utils.triple_to_string(triple)}), named_graph: {named_graph or "default"}, repository: {self._repository}" ) return False self.logger.debug( f"Found triple ({utils.triple_to_string(triple)}), named_graph: {named_graph or "default"}, repository: {self._repository}" ) return True
[docs] def triple_add( self: "GraphDB", triple: TripleLike, named_graph: Optional[GraphNameLike] = None, ) -> bool: """ Add a triple to the graph database. Args: triple (TripleLike): The triple `(subject, predicate, object)` to insert. named_graph (Optional[GraphNameLike]): Override the client's default named graph. Returns: bool: True if the triple was inserted, False otherwise. """ triple = utils.sanitize_triple(triple) named_graph = IRI(named_graph) if named_graph is not None else self.named_graph query = SPARQLQuery.insert_data( triples=[triple], named_graph=named_graph, ) result = self.query(query=query, update=True) if not result: self.logger.warning( f"Failed to insert triple: ({utils.triple_to_string(triple)}) named_graph: {named_graph or "default"}, repository: {self._repository}" ) return False self.logger.debug( f"Successfully inserted triple: ({utils.triple_to_string(triple)}) named_graph: {named_graph or "default"}, repository: {self._repository}" ) return True
[docs] def triple_delete( self: "GraphDB", triple: TripleLike, check_exist: Optional[bool] = True, named_graph: Optional[GraphNameLike] = None, ) -> bool: """ Delete a single triple. A SPARQL DELETE operation in GraphDB can be successful even if the triple does not exist. When `check_exist=True`, the function verifies the triple is present before attempting deletion. Args: triple (TripleLike): The triple `(subject, predicate, object)` to delete. check_exist (Optional[bool]): Whether to verify existence prior to deletion. Defaults to True. named_graph (Optional[GraphNameLike]): Override the client's default named graph. Returns: bool: True if deletion succeeded (or triple absent when `check_exist=False`), False otherwise. """ triple = utils.sanitize_triple(triple) named_graph = IRI(named_graph) if named_graph is not None else self.named_graph if check_exist: if not self.triple_exists(triple, named_graph=named_graph): self.logger.warning("Unable to delete triple since it does not exist") return False query = SPARQLQuery.delete_data( triples=[triple], named_graph=named_graph, ) result = self.query(query=query, update=True) if not result: self.logger.warning( f"Failed to delete triple: ({utils.triple_to_string(triple)}), named_graph: {named_graph or "default"}, repository: {self._repository}" ) return False self.logger.debug( f"Successfully deleted triple: ({utils.triple_to_string(triple)}), named_graph: {named_graph or "default"}, repository: {self._repository}" ) return True
[docs] def triple_update( self: "GraphDB", old_triple: TripleLike, new_triple: Optional[PartialTripleLike] = None, new_sub: Optional[SubjectLike] = None, new_pred: Optional[PredicateLike] = None, new_obj: Optional[ObjectLike] = None, check_exist: Optional[bool] = True, named_graph: Optional[GraphNameLike] = None, ) -> bool: """ Update a triple by replacing any of its parts. Performs a SPARQL `DELETE ... INSERT ... WHERE` that replaces the old triple with a new triple built from provided parts. Args: old_triple (TripleLike): Existing triple to update. new_triple (Optional[PartialTripleLike]): Replacement values (subject/predicate/object). Use this or `new_sub`/`new_pred`/`new_obj`. new_sub (Optional[SubjectLike]): Replacement subject. new_pred (Optional[PredicateLike]): Replacement predicate. new_obj (Optional[ObjectLike]): Replacement object. check_exist (Optional[bool]): If True, verify that `old_triple` exists before updating. Defaults to True. named_graph (Optional[GraphNameLike]): Override the client's default named graph. Returns: bool: True if the update succeeded, False otherwise. Raises: InvalidInputError: If neither or both of `new_triple` and any of `new_sub`/`new_pred`/`new_obj` are provided, or if input triples are incomplete/invalid. """ elems_given = new_sub is not None or new_pred is not None or new_obj is not None if (new_triple and elems_given) or (not new_triple and not elems_given): raise InvalidInputError( "Either 'new triple' or 'new_sub/new_pred/new_obj' must be provided, not both." ) old_triple = utils.sanitize_triple(old_triple) new_triple = utils.sanitize_triple( new_triple or (new_sub, new_pred, new_obj), allow_partial=True, ) named_graph = IRI(named_graph) if named_graph is not None else self.named_graph if check_exist: if not self.triple_exists(old_triple, named_graph=named_graph): self.logger.warning( f"Triple does not exist: ({utils.triple_to_string(old_triple)})" ) return False # Determine replacement variables update_triple = tuple(n if n else o for o, n in zip(old_triple, new_triple)) query = SPARQLQuery.delete_insert_data( delete_triples=[old_triple], insert_triples=[update_triple], where_clauses=[utils.triple_to_string(old_triple, ".")], named_graph=named_graph, ) result = self.query(query=query, update=True) if not result: self.logger.warning( f"Failed to update triple to: ({utils.triple_to_string(update_triple)}), named_graph: {named_graph or "default"}, repository: {self._repository}" ) return False self.logger.debug( f"Successfully updated triple to: ({utils.triple_to_string(update_triple)}), named_graph: {named_graph or "default"}, repository: {self._repository}" ) return True