Exemplo n.º 1
0
def get_index_kv_from_tuple(tuple_list, reverse=False):
    """ Returns keys/value of indexes for a set of entities.

  Args:
     tuple_list: A list of tuples of prefix and pb entities
     reverse: if these keys are for the descending table
  Returns:
     A list of keys and values of indexes
  """
    all_rows = []
    for prefix, entity in tuple_list:
        # Give some entities a property that makes it easy to sample keys.
        scatter_prop = get_scatter_prop(entity.key().path().element_list())
        if scatter_prop is not None:
            # Prevent the original entity from being modified.
            prop_list = [prop
                         for prop in entity.property_list()] + [scatter_prop]
        else:
            prop_list = entity.property_list()

        for prop in prop_list:
            val = str(encode_index_pb(prop.value()))

            if reverse:
                val = helper_functions.reverse_lex(val)

            params = [
                prefix,
                get_entity_kind(entity),
                prop.name(), val,
                str(encode_index_pb(entity.key().path()))
            ]

            index_key = get_index_key_from_params(params)
            p_vals = [index_key,
                      buffer(prefix + dbconstants.KEY_DELIMITER) + \
                      encode_index_pb(entity.key().path())]
            all_rows.append(p_vals)
    return tuple(all_rows)
Exemplo n.º 2
0
def get_index_kv_from_tuple(tuple_list, reverse=False):
  """ Returns keys/value of indexes for a set of entities.

  Args:
     tuple_list: A list of tuples of prefix and pb entities
     reverse: if these keys are for the descending table
  Returns:
     A list of keys and values of indexes
  """
  all_rows = []
  for prefix, entity in tuple_list:
    # Give some entities a property that makes it easy to sample keys.
    scatter_prop = get_scatter_prop(entity.key().path().element_list())
    if scatter_prop is not None:
      # Prevent the original entity from being modified.
      prop_list = [prop for prop in entity.property_list()] + [scatter_prop]
    else:
      prop_list = entity.property_list()

    for prop in prop_list:
      val = str(encode_index_pb(prop.value()))

      if reverse:
        val = helper_functions.reverse_lex(val)

      params = [prefix,
                get_entity_kind(entity),
                prop.name(),
                val,
                str(encode_index_pb(entity.key().path()))]

      index_key = get_index_key_from_params(params)
      p_vals = [index_key,
                buffer(prefix + dbconstants.KEY_DELIMITER) + \
                encode_index_pb(entity.key().path())]
      all_rows.append(p_vals)
  return tuple(all_rows)
Exemplo n.º 3
0
def get_composite_index_keys(index, entity):
    """ Creates keys to the composite index table for a given entity.

  Keys are built as such:
    app_id/ns/composite_id/ancestor/valuevaluevalue..../entity_key
  Components explained:
  ns: The namespace of the entity.
  composite_id: The composite ID assigned to this index upon creation.
  ancestor: The root ancestor path (only if the query this index is for
    has an ancestor)
  value(s): The string representation of mulitiple properties.
  entity_key: The entity key (full path) used as a means of having a unique
    identifier. This prevents two entities with the same values from
    colliding.

  Args:
    index: A datastore_pb.CompositeIndex.
    entity: A entity_pb.EntityProto.
  Returns:
    A list of strings representing keys to the composite table.
  """
    composite_id = index.id()
    definition = index.definition()
    app_id = clean_app_id(entity.key().app())
    name_space = entity.key().name_space()
    ent_key = encode_index_pb(entity.key().path())
    pre_comp_index_key = "{0}{1}{2}{4}{3}{4}".format(app_id,
                                                     dbconstants.KEY_DELIMITER,
                                                     name_space, composite_id,
                                                     dbconstants.KEY_DELIMITER)
    if definition.ancestor() == 1:
        ancestor_list = get_ancestor_paths_from_ent_key(ent_key)

    property_list_names = [prop.name() for prop in entity.property_list()]
    multivalue_dict = {}
    for prop in entity.property_list():
        if prop.name() not in property_list_names:
            continue
        value = str(encode_index_pb(prop.value()))

        if prop.name() in multivalue_dict:
            multivalue_dict[prop.name()].append(value)
        else:
            multivalue_dict[prop.name()] = [value]
    # Build lists for which we'll get all combinations of indexes.
    lists_of_prop_list = []
    for prop in definition.property_list():
        # Check to make sure the entity has the required items. If not then we
        # do not create an index for the composite index.
        # The definition can also have a key as a part of the index, but this
        # is not repeated.
        if prop.name() == "__key__":
            value = str(encode_index_pb(entity.key().path()))
            if prop.direction() == entity_pb.Index_Property.DESCENDING:
                value = helper_functions.reverse_lex(value)
            lists_of_prop_list.append([value])
        elif prop.name() not in multivalue_dict:
            return []
        else:
            my_list = multivalue_dict[prop.name()]
            if prop.direction() == entity_pb.Index_Property.DESCENDING:
                for index, item in enumerate(my_list):
                    my_list[index] = helper_functions.reverse_lex(item)
            lists_of_prop_list.append(my_list)

    # Get all combinations of the composite indexes.
    all_combinations = []
    if len(lists_of_prop_list) == 1:
        for item in lists_of_prop_list[0]:
            all_combinations.append([item])
    elif len(lists_of_prop_list) > 1:
        all_combinations = list(itertools.product(*lists_of_prop_list))

    # We should throw an exception if the number of combinations is
    # more than 20000. We currently do not.
    # https://developers.google.com/appengine/docs/python/datastore/
    # #Python_Quotas_and_limits

    all_keys = []
    for combo in all_combinations:
        index_value = ""
        for prop_value in combo:
            index_value += str(prop_value) + dbconstants.KEY_DELIMITER

        # We append the ent key to have unique keys if entities happen
        # to share the same index values (and ancestor).
        if definition.ancestor() == 1:
            for ancestor in ancestor_list:
                pre_comp_key = pre_comp_index_key + "{0}{1}".format(
                    ancestor, dbconstants.KEY_DELIMITER)
                composite_key = "{0}{1}{2}".format(pre_comp_key, index_value,
                                                   ent_key)
                all_keys.append(composite_key)
        else:
            composite_key = "{0}{1}{2}".format(pre_comp_index_key, index_value,
                                               ent_key)
            all_keys.append(composite_key)

    return all_keys
Exemplo n.º 4
0
def get_composite_index_keys(index, entity):
  """ Creates keys to the composite index table for a given entity.

  Keys are built as such:
    app_id/ns/composite_id/ancestor/valuevaluevalue..../entity_key
  Components explained:
  ns: The namespace of the entity.
  composite_id: The composite ID assigned to this index upon creation.
  ancestor: The root ancestor path (only if the query this index is for
    has an ancestor)
  value(s): The string representation of mulitiple properties.
  entity_key: The entity key (full path) used as a means of having a unique
    identifier. This prevents two entities with the same values from
    colliding.

  Args:
    index: A datastore_pb.CompositeIndex.
    entity: A entity_pb.EntityProto.
  Returns:
    A list of strings representing keys to the composite table.
  """
  composite_id = index.id()
  definition = index.definition()
  app_id = clean_app_id(entity.key().app())
  name_space = entity.key().name_space()
  ent_key = encode_index_pb(entity.key().path())
  pre_comp_index_key = "{0}{1}{2}{4}{3}{4}".format(app_id,
                                                   dbconstants.KEY_DELIMITER,
                                                   name_space, composite_id,
                                                   dbconstants.KEY_DELIMITER)
  if definition.ancestor() == 1:
    ancestor_list = get_ancestor_paths_from_ent_key(ent_key)

  property_list_names = [prop.name() for prop in entity.property_list()]
  multivalue_dict = {}
  for prop in entity.property_list():
    if prop.name() not in property_list_names:
      continue
    value = str(encode_index_pb(prop.value()))

    if prop.name() in multivalue_dict:
      multivalue_dict[prop.name()].append(value)
    else:
      multivalue_dict[prop.name()] = [value]
  # Build lists for which we'll get all combinations of indexes.
  lists_of_prop_list = []
  for prop in definition.property_list():
    # Check to make sure the entity has the required items. If not then we
    # do not create an index for the composite index.
    # The definition can also have a key as a part of the index, but this
    # is not repeated.
    if prop.name() == "__key__":
      value = str(encode_index_pb(entity.key().path()))
      if prop.direction() == entity_pb.Index_Property.DESCENDING:
        value = helper_functions.reverse_lex(value)
      lists_of_prop_list.append([value])
    elif prop.name() not in multivalue_dict:
      return []
    else:
      my_list = multivalue_dict[prop.name()]
      if prop.direction() == entity_pb.Index_Property.DESCENDING:
        for index, item in enumerate(my_list):
          my_list[index] = helper_functions.reverse_lex(item)
      lists_of_prop_list.append(my_list)

  # Get all combinations of the composite indexes.
  all_combinations = []
  if len(lists_of_prop_list) == 1:
    for item in lists_of_prop_list[0]:
      all_combinations.append([item])
  elif len(lists_of_prop_list) > 1:
    all_combinations = list(itertools.product(*lists_of_prop_list))

  # We should throw an exception if the number of combinations is
  # more than 20000. We currently do not.
  # https://developers.google.com/appengine/docs/python/datastore/
  # #Python_Quotas_and_limits

  all_keys = []
  for combo in all_combinations:
    index_value = ""
    for prop_value in combo:
      index_value += str(prop_value) + dbconstants.KEY_DELIMITER

    # We append the ent key to have unique keys if entities happen
    # to share the same index values (and ancestor).
    if definition.ancestor() == 1:
      for ancestor in ancestor_list:
        pre_comp_key = pre_comp_index_key + "{0}{1}".format(
          ancestor, dbconstants.KEY_DELIMITER)
        composite_key = "{0}{1}{2}".format(pre_comp_key, index_value,
                                           ent_key)
        all_keys.append(composite_key)
    else:
      composite_key = "{0}{1}{2}".format(pre_comp_index_key, index_value,
                                         ent_key)
      all_keys.append(composite_key)

  return all_keys