示例#1
0
    def _ValidateQuery(self, query, query_info):
        """Ensure that the given query matches the query_info.

    Args:
      query: datastore_pb.Query instance we are chacking
      query_info: datastore_pb.Query instance we want to match

    Raises BadRequestError on failure.
    """
        error_msg = 'Cursor does not match query: %s'
        if query_info.filter_list() != query.filter_list():
            raise BadRequestError(error_msg % 'filters do not match')
        if query_info.order_list() != query.order_list():
            raise BadRequestError(error_msg % 'orders do not match')

        for attr in ('ancestor', 'kind', 'name_space', 'search_query'):
            query_info_has_attr = getattr(query_info, 'has_%s' % attr)
            query_info_attr = getattr(query_info, attr)
            query_has_attr = getattr(query, 'has_%s' % attr)
            query_attr = getattr(query, attr)
            if query_info_has_attr():
                if not query_has_attr() or query_info_attr() != query_attr():
                    raise BadRequestError(error_msg %
                                          ('%s does not match' % attr))
            elif query_has_attr():
                raise BadRequestError(error_msg % ('%s does not match' % attr))
示例#2
0
def ParsePropertyQuery(query, filters, orders):
    """Parse __property__  queries.

  Raises exceptions for illegal queries.
  Args:
    query: A Query PB.
    filters: the normalized filters from query.
    orders: the normalized orders from query.
  Returns:
     The kind range (a ValueRange over (kind, property) pairs) requested
     in the query.
  """
    if query.has_transaction():
        raise BadRequestError(
            'transactional queries on __property__ not allowed')

    key_range = ParseKeyFilteredQuery(filters, orders)
    key_range.Remap(lambda x: _PropertyKeyToString(x, ''))

    if query.has_ancestor():
        ancestor = datastore_types.Key._FromPb(query.ancestor())
        ancestor_kind, ancestor_property = _PropertyKeyToString(ancestor, None)

        if ancestor_property is not None:
            key_range.Update(datastore_pb.Query_Filter.EQUAL,
                             (ancestor_kind, ancestor_property))
        else:
            key_range.Update(datastore_pb.Query_Filter.GREATER_THAN_OR_EQUAL,
                             (ancestor_kind, ''))
            key_range.Update(datastore_pb.Query_Filter.LESS_THAN_OR_EQUAL,
                             (ancestor_kind + '\0', ''))
        query.clear_ancestor()

    return key_range
示例#3
0
def ParseKeyFilteredQuery(filters, orders):
    """Parse queries which only allow filters and ascending-orders on __key__.

  Raises exceptions for illegal queries.
  Args:
    filters: the normalized filters of a query.
    orders: the normalized orders of a query.
  Returns:
     The key range (a ValueRange over datastore_types.Key) requested in the
     query.
  """

    remaining_filters = []
    key_range = ValueRange()
    key_prop = datastore_types._KEY_SPECIAL_PROPERTY
    for f in filters:
        op = f.op()
        if not (f.property_size() == 1 and f.property(0).name() == key_prop
                and not (op == datastore_pb.Query_Filter.IN
                         or op == datastore_pb.Query_Filter.EXISTS)):
            remaining_filters.append(f)
            continue

        val = f.property(0).value()
        if not val.has_referencevalue():
            raise BadRequestError('__key__ kind must be compared to a key')
        limit = datastore_types.FromReferenceProperty(val)
        key_range.Update(op, limit)

    remaining_orders = []
    for o in orders:
        if not (o.direction() == datastore_pb.Query_Order.ASCENDING
                and o.property() == datastore_types._KEY_SPECIAL_PROPERTY):
            remaining_orders.append(o)
        else:
            break

    if remaining_filters:
        raise BadRequestError('Only comparison filters on ' + key_prop +
                              ' supported')
    if remaining_orders:
        raise BadRequestError('Only ascending order on ' + key_prop +
                              ' supported')

    return key_range
示例#4
0
def _KindKeyToString(key):
    """Extract kind name from __kind__ key.

  Raises an ApplicationError if the key is not of the form '__kind__'/name.

  Args:
    key: a key for a __kind__ instance.
  Returns:
    kind specified by key.
  """
    key_path = key.to_path()
    if (len(key_path) == 2 and key_path[0] == '__kind__'
            and isinstance(key_path[1], basestring)):
        return key_path[1]
    raise BadRequestError('invalid Key for __kind__ table')
示例#5
0
def _NamespaceKeyToString(key):
    """Extract namespace name from __namespace__ key.

  Raises an ApplicationError if the key is not of the form '__namespace__'/name
  or '__namespace__'/_EMPTY_NAMESPACE_ID.

  Args:
    key: a key for a __namespace__ instance.
  Returns:
    namespace specified by key.
  """
    key_path = key.to_path()
    if len(key_path) == 2 and key_path[0] == '__namespace__':
        if key_path[1] == datastore_types._EMPTY_NAMESPACE_ID:
            return ''
        if isinstance(key_path[1], basestring):
            return key_path[1]
    raise BadRequestError('invalid Key for __namespace__ table')
示例#6
0
def ParseNamespaceQuery(query, filters, orders):
    """Parse __namespace__  queries.

  Raises exceptions for illegal queries.
  Args:
    query: A Query PB.
    filters: the normalized filters from query.
    orders: the normalized orders from query.
  Returns:
     The kind range (a ValueRange over string) requested in the query.
  """
    if query.has_ancestor():
        raise BadRequestError('ancestor queries on __namespace__ not allowed')

    key_range = ParseKeyFilteredQuery(filters, orders)
    key_range.Remap(_NamespaceKeyToString)

    return key_range
示例#7
0
def _PropertyKeyToString(key, default_property):
    """Extract property name from __property__ key.

  Raises an ApplicationError if the key is not of the form
  '__kind__'/kind, '__property__'/property or '__kind__'/kind

  Args:
    key: a key for a __property__ instance.
    default_property: property value to return when key only has a kind.
  Returns:
    kind, property if key = '__kind__'/kind, '__property__'/property
    kind, default_property if key = '__kind__'/kind
  """
    key_path = key.to_path()
    if (len(key_path) == 2 and key_path[0] == '__kind__'
            and isinstance(key_path[1], basestring)):
        return (key_path[1], default_property)
    if (len(key_path) == 4 and key_path[0] == '__kind__'
            and isinstance(key_path[1], basestring)
            and key_path[2] == '__property__'
            and isinstance(key_path[3], basestring)):
        return (key_path[1], key_path[3])

    raise BadRequestError('invalid Key for __property__ table')