thirdparty/google_appengine/google/appengine/datastore/datastore_index.py
changeset 686 df109be0567c
parent 109 620f9b141567
child 828 f5fd65cc3bf3
equal deleted inserted replaced
685:a440ced9a75f 686:df109be0567c
    47 
    47 
    48 
    48 
    49 
    49 
    50 
    50 
    51 
    51 
       
    52 from google.appengine.api import datastore_types
    52 from google.appengine.api import validation
    53 from google.appengine.api import validation
    53 from google.appengine.api import yaml_errors
    54 from google.appengine.api import yaml_errors
    54 from google.appengine.api import yaml_object
    55 from google.appengine.api import yaml_object
    55 from google.appengine.datastore import datastore_pb
    56 from google.appengine.datastore import datastore_pb
    56 
    57 
   247 
   248 
   248   Args:
   249   Args:
   249     query: A datastore_pb.Query instance.
   250     query: A datastore_pb.Query instance.
   250 
   251 
   251   Returns:
   252   Returns:
   252     None if no composite index is needed for this query.  Otherwise,
   253     A tuple of the form (required, kind, ancestor, (prop1, prop2, ...), neq):
   253     a tuple of the form (kind, ancestor, (prop1, prop2, ...), neq) where:
   254       required: boolean, whether the index is required
   254       kind: the kind or None;
   255       kind: the kind or None;
   255       ancestor: True if this is an ancestor query;
   256       ancestor: True if this is an ancestor query;
   256       prop1, prop2, ...: tuples of the form (name, direction) where:
   257       prop1, prop2, ...: tuples of the form (name, direction) where:
   257         name: a property name;
   258         name: a property name;
   258         direction: datastore_pb.Query_Order.ASCENDING or ...DESCENDING;
   259         direction: datastore_pb.Query_Order.ASCENDING or ...DESCENDING;
   259       neq: the number of prop tuples corresponding to equality filters.
   260       neq: the number of prop tuples corresponding to equality filters.
   260   """
   261   """
       
   262   required = True
       
   263 
   261   kind = query.kind()
   264   kind = query.kind()
   262   ancestor = query.has_ancestor()
   265   ancestor = query.has_ancestor()
   263   filters = query.filter_list()
   266   filters = query.filter_list()
   264   orders = query.order_list()
   267   orders = query.order_list()
   265 
   268 
   267     assert filter.op() != datastore_pb.Query_Filter.IN, 'Filter.op()==IN'
   270     assert filter.op() != datastore_pb.Query_Filter.IN, 'Filter.op()==IN'
   268     nprops = len(filter.property_list())
   271     nprops = len(filter.property_list())
   269     assert nprops == 1, 'Filter has %s properties, expected 1' % nprops
   272     assert nprops == 1, 'Filter has %s properties, expected 1' % nprops
   270 
   273 
   271   if ancestor and not kind and not filters and not orders:
   274   if ancestor and not kind and not filters and not orders:
   272     return None
   275     required = False
   273 
   276 
   274   eq_filters = [f for f in filters if f.op() in EQUALITY_OPERATORS]
   277   eq_filters = [f for f in filters if f.op() in EQUALITY_OPERATORS]
   275   ineq_filters = [f for f in filters if f.op() in INEQUALITY_OPERATORS]
   278   ineq_filters = [f for f in filters if f.op() in INEQUALITY_OPERATORS]
   276   exists_filters = [f for f in filters if f.op() in EXISTS_OPERATORS]
   279   exists_filters = [f for f in filters if f.op() in EXISTS_OPERATORS]
   277   assert (len(eq_filters) + len(ineq_filters) +
   280   assert (len(eq_filters) + len(ineq_filters) +
   278           len(exists_filters)) == len(filters), 'Not all filters used'
   281           len(exists_filters)) == len(filters), 'Not all filters used'
   279 
   282 
   280   if (kind and eq_filters and not ineq_filters and not exists_filters and
   283   if (kind and eq_filters and not ineq_filters and not exists_filters and
   281       not orders):
   284       not orders):
   282     return None
   285     names = set(f.property(0).name() for f in eq_filters)
       
   286     if not names.intersection(datastore_types._SPECIAL_PROPERTIES):
       
   287       required = False
   283 
   288 
   284   ineq_property = None
   289   ineq_property = None
   285   if ineq_filters:
   290   if ineq_filters:
   286     ineq_property = ineq_filters[0].property(0).name()
   291     ineq_property = ineq_filters[0].property(0).name()
   287     for filter in ineq_filters:
   292     for filter in ineq_filters:
   323     else:
   328     else:
   324       props.append((prop_name, ASCENDING))
   329       props.append((prop_name, ASCENDING))
   325 
   330 
   326   if (kind and not ancestor and
   331   if (kind and not ancestor and
   327       (not props or (len(props) == 1 and props[0][1] == ASCENDING))):
   332       (not props or (len(props) == 1 and props[0][1] == ASCENDING))):
   328     return None
   333     required = False
   329 
   334 
   330   unique_names = set(name for name, dir in props)
   335   unique_names = set(name for name, dir in props)
   331   if len(props) > 1 and len(unique_names) == 1:
   336   if len(props) > 1 and len(unique_names) == 1:
   332     return None
   337     required = False
   333 
   338 
   334   return (kind, ancestor, tuple(props), len(eq_filters))
   339   return (required, kind, ancestor, tuple(props), len(eq_filters))
   335 
   340 
   336 
   341 
   337 def IndexYamlForQuery(kind, ancestor, props):
   342 def IndexYamlForQuery(kind, ancestor, props):
   338   """Return the composite index definition YAML needed for a query.
   343   """Return the composite index definition YAML needed for a query.
   339 
   344