text: # Copyright © 2020 Interplanetary Database Association e.V.,
  # Planetmint and IPDB software contributors.
  # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
  # Code is Apache-2.0 and docs are CC-BY-4.0
  
  """Query interfaces for backends."""
  
  from functools import singledispatch
  
  from planetmint.backend.exceptions import OperationError
  
  
  @singledispatch
  def store_asset(connection, asset):
      """Write an asset to the asset table.
  
      Args:
          asset (dict): the asset.
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_assets(connection, assets):
      """Write a list of assets to the assets table.
  
      Args:
          assets (list): a list of assets to write.
  
      Returns:
          The database response.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_metadatas(connection, metadata):
      """Write a list of metadata to metadata table.
  
      Args:
          metadata (list): list of metadata.
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_transactions(connection, signed_transactions):
      """Store the list of transactions."""
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_transaction(connection, transaction_id):
      """Get a transaction from the transactions table.
  
      Args:
          transaction_id (str): the id of the transaction.
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_transactions(connection, transaction_ids):
      """Get transactions from the transactions table.
  
      Args:
          transaction_ids (list): list of transaction ids to fetch
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_asset(connection, asset_id):
      """Get a transaction from the transactions table.
  
      Args:
          asset_id (str): the id of the asset
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_spent(connection, transaction_id, condition_id):
      """Check if a `txid` was already used as an input.
  
      A transaction can be used as an input for another transaction. Bigchain
      needs to make sure that a given `txid` is only used once.
  
      Args:
          transaction_id (str): The id of the transaction.
          condition_id (int): The index of the condition in the respective
              transaction.
  
      Returns:
          The transaction that used the `txid` as an input else `None`
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_spending_transactions(connection, inputs):
      """Return transactions which spend given inputs
  
      Args:
          inputs (list): list of {txid, output}
  
      Returns:
          Iterator of (block_ids, transaction) for transactions that
          spend given inputs.
      """
      raise NotImplementedError
  
  
  @singledispatch
  def get_owned_ids(connection, owner):
      """Retrieve a list of `txids` that can we used has inputs.
  
      Args:
          owner (str): base58 encoded public key.
  
      Returns:
          Iterator of (block_id, transaction) for transactions
          that list given owner in conditions.
      """
      raise NotImplementedError
  
  
  @singledispatch
  def get_block(connection, block_id):
      """Get a block from the planet table.
  
      Args:
          block_id (str): block id of the block to get
  
      Returns:
          block (dict): the block or `None`
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_block_with_transaction(connection, txid):
      """Get a block containing transaction id `txid`
  
      Args:
          txid (str): id of transaction to be searched.
  
      Returns:
          block_id (int): the block id or `None`
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_metadata(connection, transaction_ids):
      """Get a list of metadata from the metadata table.
  
      Args:
          transaction_ids (list): a list of ids for the metadata to be retrieved from
          the database.
  
      Returns:
          metadata (list): the list of returned metadata.
      """
      raise NotImplementedError
  
  
  @singledispatch
  def get_assets(connection, asset_ids):
      """Get a list of assets from the assets table.
      Args:
          asset_ids (list): a list of ids for the assets to be retrieved from
          the database.
      Returns:
          assets (list): the list of returned assets.
      """
      raise NotImplementedError
  
  
  @singledispatch
  def get_txids_filtered(connection, asset_id, operation=None):
      """Return all transactions for a particular asset id and optional operation.
  
      Args:
          asset_id (str): ID of transaction that defined the asset
          operation (str) (optional): Operation to filter on
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def text_search(conn, search, *, language='english', case_sensitive=False,
                  diacritic_sensitive=False, text_score=False, limit=0, table=None):
      """Return all the assets that match the text search.
  
      The results are sorted by text score.
      For more information about the behavior of text search on MongoDB see
      https://docs.mongodb.com/manual/reference/operator/query/text/#behavior
  
      Args:
          search (str): Text search string to query the text index
          language (str, optional): The language for the search and the rules for
              stemmer and tokenizer. If the language is ``None`` text search uses
              simple tokenization and no stemming.
          case_sensitive (bool, optional): Enable or disable case sensitive
              search.
          diacritic_sensitive (bool, optional): Enable or disable case sensitive
              diacritic search.
          text_score (bool, optional): If ``True`` returns the text score with
              each document.
          limit (int, optional): Limit the number of returned documents.
  
      Returns:
          :obj:`list` of :obj:`dict`: a list of assets
  
      Raises:
          OperationError: If the backend does not support text search
      """
  
      raise OperationError('This query is only supported when running '
                           'Planetmint with MongoDB as the backend.')
  
  
  @singledispatch
  def get_latest_block(conn):
      """Get the latest commited block i.e. block with largest height"""
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_block(conn, block):
      """Write a new block to the `blocks` table
  
      Args:
          block (dict): block with current height and block hash.
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_unspent_outputs(connection, unspent_outputs):
      """Store unspent outputs in ``utxo_set`` table."""
  
      raise NotImplementedError
  
  
  @singledispatch
  def delete_unspent_outputs(connection, unspent_outputs):
      """Delete unspent outputs in ``utxo_set`` table."""
  
      raise NotImplementedError
  
  
  @singledispatch
  def delete_transactions(conn, txn_ids):
      """Delete transactions from database
  
      Args:
          txn_ids (list): list of transaction ids
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_unspent_outputs(connection, *, query=None):
      """Retrieves unspent outputs.
  
      Args:
          query (dict): An optional parameter to filter the result set.
              Defaults to ``None``, which means that all UTXO records
              will be returned.
  
      Returns:
          Generator yielding unspent outputs (UTXO set) according to the
          given query.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_pre_commit_state(connection, state):
      """Store pre-commit state.
  
      Args:
          state (dict): pre-commit state.
  
      Returns:
          The result of the operation.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_pre_commit_state(connection):
      """Get pre-commit state.
  
      Returns:
          Document representing the pre-commit state.
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_validator_set(conn, validator_update):
      """Store updated validator set"""
  
      raise NotImplementedError
  
  
  @singledispatch
  def delete_validator_set(conn, height):
      """Delete the validator set at the given height."""
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_election(conn, election_id, height, is_concluded):
      """Store election record"""
  
      raise NotImplementedError
  
  
  @singledispatch
  def store_elections(conn, elections):
      """Store election records in bulk"""
  
      raise NotImplementedError
  
  
  @singledispatch
  def delete_elections(conn, height):
      """Delete all election records at the given height"""
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_validator_set(conn, height):
      """Get validator set for a given `height`, if `height` is not specified
      then return the latest validator set
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_election(conn, election_id):
      """Return the election record
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_asset_tokens_for_public_key(connection, asset_id, public_key):
      """Retrieve a list of tokens of type `asset_id` that are owned by the `public_key`.
      Args:
          asset_id (str): Id of the token.
          public_key (str): base58 encoded public key
      Returns:
          Iterator of transaction that list given owner in conditions.
      """
      raise NotImplementedError
  
  
  @singledispatch
  def store_abci_chain(conn, height, chain_id, is_synced=True):
      """Create or update an ABCI chain at the given height.
      Usually invoked in the beginning of the ABCI communications (height=0)
      or when ABCI client (like Tendermint) is migrated (any height).
  
      Args:
          is_synced: True if the chain is known by both ABCI client and server
      """
  
      raise NotImplementedError
  
  
  @singledispatch
  def delete_abci_chain(conn, height):
      """Delete the ABCI chain at the given height."""
  
      raise NotImplementedError
  
  
  @singledispatch
  def get_latest_abci_chain(conn):
      """Returns the ABCI chain stored at the biggest height, if any,
      None otherwise.
      """
      raise NotImplementedError
  