def validate_commit_req(self, req):
        """Validates a normalized CommitRequest.

    Args:
      req: a googledatastore.CommitRequest

    Raises:
      ValidationError: if the request is invalid
    """
        _assert_initialized(req)
        if (req.mode == googledatastore.CommitRequest.MODE_UNSPECIFIED
                or req.mode == googledatastore.CommitRequest.TRANSACTIONAL):
            _assert_condition(req.WhichOneof('transaction_selector'),
                              'Transactional commit requires a transaction.')
            if req.WhichOneof('transaction_selector') == 'transaction':
                _assert_condition(
                    req.transaction, 'a transaction cannot be the empty '
                    'string.')

            seen_base_versions = {}
            for mutation in req.mutations:
                v1_key, _ = datastore_pbs.get_v1_mutation_key_and_entity(
                    mutation)
                if datastore_pbs.is_complete_v1_key(v1_key):
                    mutation_base_version = None
                    if mutation.HasField('base_version'):
                        mutation_base_version = mutation.base_version

                    key = datastore_types.ReferenceToKeyValue(
                        v1_key, self.__id_resolver)
                    if key in seen_base_versions:
                        _assert_condition(
                            seen_base_versions[key] == mutation_base_version,
                            'Mutations for the same entity must have the '
                            'same base version.')
                    seen_base_versions[key] = mutation_base_version

        elif req.mode == googledatastore.CommitRequest.NON_TRANSACTIONAL:
            _assert_condition(
                not req.WhichOneof('transaction_selector'),
                'Non-transactional commit cannot specify a '
                'transaction.')

            seen_complete_keys = set()
            for mutation in req.mutations:
                v1_key, _ = datastore_pbs.get_v1_mutation_key_and_entity(
                    mutation)
                if datastore_pbs.is_complete_v1_key(v1_key):
                    key = datastore_types.ReferenceToKeyValue(
                        v1_key, self.__id_resolver)
                    _assert_condition(
                        key not in seen_complete_keys,
                        'A non-transactional commit may not contain '
                        'multiple mutations affecting the same entity.')
                    seen_complete_keys.add(key)

        for mutation in req.mutations:
            self.__validate_mutation(mutation)
Пример #2
0
  def _GetEntitiesInEntityGroup(self, entity_group):
    query = datastore_pb.Query()
    query.set_app(entity_group.app())
    if entity_group.name_space():
      query.set_name_space(entity_group.name_space())
    query.mutable_ancestor().CopyFrom(entity_group)

    filter_info = self.__GenerateFilterInfo(query.filter_list(), query)
    order_info = self.__GenerateOrderInfo(query.order_list())
    sql_stmt, params = self.__KindQuery(query, filter_info, order_info)






    conn = self._GetConnection()
    try:
      db_cursor = conn.execute(sql_stmt, params)
      entities = {}
      for row in db_cursor.fetchall():
        entity = entity_pb.EntityProto(row[1])
        key = datastore_types.ReferenceToKeyValue(entity.key())
        entities[key] = datastore_stub_util._FromStorageEntity(entity)
      return entities
    finally:

      self._ReleaseConnection(conn)
  def _GetEntitiesInEntityGroup(self, entity_group):
    connection = self._GetConnection()

    if isinstance(entity_group, entity_pb.Reference):
      req = googledatastore.LookupRequest()
      v1_key = req.key.add()
      converter.v3_entity_ref_to_v1_key(entity_group, v1_key)

      v1_key.partition_id.Clear()

      resp = connection.lookup(req)

      if resp.found:
        v3_entities = []
        for v1_entity_result in resp.found:
          v3_entity = entity_pb.EntityProto()
          converter.v1_to_v3_entity(v1_entity_result.entity, v3_entity)
          v3_entity.mutable_key().set_app(entity_group.app())
          v3_entity.mutable_key().set_name_space(entity_group.name_space())
          v3_entities.append(v3_entity)

        return dict((datastore_types.ReferenceToKeyValue(entity.key()), entity)
                  for entity in v3_entities)

    return {}
  def __apply_v1_mutation(self, v1_mutation, base_version, v1_txn,
                          version_cache):
    """Applies a v1 Mutation in a transaction.

    Args:
      v1_mutation: a googledatastore.Mutation, must be for a complete key.
      base_version: optional, the version the entity is expected to be at. If
          the entity has a different version number, the mutation does not
          apply. If None, then this check is skipped.
      v1_txn: a v1 transaction handle
      version_cache: a cache of entity keys to version, for entities that have
          been mutated previously in this transaction.
    """
    v1_key, v1_entity = datastore_pbs.get_v1_mutation_key_and_entity(
        v1_mutation)
    key = datastore_types.ReferenceToKeyValue(v1_key, self._id_resolver)



    if (v1_mutation.HasField('insert') or v1_mutation.HasField('update') or
        base_version is not None) and key not in version_cache:
      version_cache[key] = self.__get_v1_entity_version(v1_key, v1_txn)

    if v1_mutation.HasField('insert'):
      if base_version is not None and base_version != _NO_VERSION:
        raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
                                               'Cannot insert an entity with a '
                                               'base version greater than zero')
      elif version_cache[key] != _NO_VERSION:
        raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
                                               'Entity already exists.')
    elif v1_mutation.HasField('update'):
      if base_version is not None and base_version == _NO_VERSION:
        raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
                                               'Cannot update an entity with a '
                                               'base version set to zero')
      elif version_cache[key] == _NO_VERSION:
        raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
                                               'Entity does not exist.')


    if base_version is not None:
      persisted_version = version_cache[key]
      if persisted_version != _NO_VERSION and persisted_version < base_version:
        raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
                                               'Invalid base version, it is '
                                               'greater than the stored '
                                               'version')
      if persisted_version != base_version:
        return persisted_version


    if v1_mutation.HasField('delete'):
      self.__delete_v1_key(v1_key, v1_txn)
      version_cache[key] = _NO_VERSION
    else:
      self.__put_v1_entity(v1_entity, v1_txn)
      version_cache[key] = _MINIMUM_VERSION
Пример #5
0
  def _GetEntityLocation(self, key):
    """Get keys to self.__entities_by_* from the given key.

    Example usage:
      app_kind, eg_k, k = self._GetEntityLocation(key)
      self.__entities_by_kind[app_kind][k]
      self.__entities_by_entity_group[eg_k][k]

    Args:
      key: entity_pb.Reference

    Returns:
      Tuple (by_kind key, by_entity_group key, entity key)
    """
    app_ns = datastore_types.EncodeAppIdNamespace(key.app(), key.name_space())
    kind = key.path().element_list()[-1].type()
    entity_group = datastore_stub_util._GetEntityGroup(key)
    eg_k = datastore_types.ReferenceToKeyValue(entity_group)
    k = datastore_types.ReferenceToKeyValue(key)

    return ((app_ns, kind), eg_k, k)
Пример #6
0
 def _GetEntitiesInEntityGroup(self, entity_group):
     eg_k = datastore_types.ReferenceToKeyValue(entity_group)
     return self.__entities_by_group[eg_k].copy()
Пример #7
0
 def _GetEntitiesInEntityGroup(self, entity_group):
     eg_k = datastore_types.ReferenceToKeyValue(entity_group)
     return dict((k, e.record)
                 for (k, e) in self.__entities_by_group[eg_k].iteritems())
  def __commit(self, v1_mutations, v1_txn, resp):
    """Commits a list of v1 mutations.

    Args:
      v1_mutations: the list of mutations to apply and commit
      v1_txn: required v1 transaction handle in which to apply the mutations
      resp: a v1 CommitResponse to update with the result of this commit
    """


    mutation_keys = []


    seen_keys = set()


    allocated_keys = {}


    conflict_cache = {}


    version_cache = {}

    for i, mutation in enumerate(v1_mutations):
      v1_key, v1_entity = datastore_pbs.get_v1_mutation_key_and_entity(mutation)
      key = datastore_types.ReferenceToKeyValue(v1_key, self._id_resolver)
      if not datastore_pbs.is_complete_v1_key(v1_key):

        v1_key = self.__put_v1_entity(v1_entity, v1_txn)
        key = datastore_types.ReferenceToKeyValue(v1_key, self._id_resolver)
        allocated_keys[key] = v1_key
      elif key not in conflict_cache:


        base_version = None
        if mutation.HasField('base_version') and key not in seen_keys:
          base_version = mutation.base_version

        conflict_version = self.__apply_v1_mutation(mutation, base_version,
                                                    v1_txn, version_cache)
        if conflict_version is not None:
          conflict_cache[key] = conflict_version

      mutation_keys.append(key)
      seen_keys.add(key)

    v3_txn = datastore_pb.Transaction()
    self.__service_converter.v1_to_v3_txn(v1_txn, v3_txn)
    v3_resp = datastore_pb.CommitResponse()
    self.__make_v3_call('Commit', v3_txn, v3_resp)
    resp.index_updates = v3_resp.cost().index_writes()



    mutation_versions = {}
    for version in v3_resp.version_list():
      key = datastore_types.ReferenceToKeyValue(version.root_entity_key())
      mutation_versions[key] = version.version()

    for key in mutation_keys:
      mutation_result = resp.mutation_results.add()
      if key in allocated_keys:
        mutation_result.key.CopyFrom(allocated_keys[key])
      if key in conflict_cache:
        mutation_result.conflict_detected = True
        mutation_result.version = conflict_cache[key]
      else:
        mutation_result.version = mutation_versions[key]