Chromium Code Reviews| Index: service/datastore/query.go |
| diff --git a/service/datastore/query.go b/service/datastore/query.go |
| index 74ed2f0ec293a21df613bd7a672091dd7a8f4977..c0d95551fd1402a63887b42c43b85c1a0827b9f9 100644 |
| --- a/service/datastore/query.go |
| +++ b/service/datastore/query.go |
| @@ -470,14 +470,24 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
| return q.finalized, q.err |
| } |
| + ancestor := (*Key)(nil) |
| + if slice, ok := q.eqFilts["__ancestor__"]; ok { |
| + ancestor = slice[0].Value().(*Key) |
| + } |
| + |
| err := func() error { |
| + |
| if q.kind == "" { // kindless query checks |
| if q.ineqFiltProp != "" && q.ineqFiltProp != "__key__" { |
| return fmt.Errorf( |
| "kindless queries can only filter on __key__, got %q", q.ineqFiltProp) |
| } |
| - if len(q.eqFilts) > 0 { |
| - return fmt.Errorf("kindless queries not have any equality filters") |
| + allowedEqs := 0 |
| + if ancestor != nil { |
| + allowedEqs = 1 |
| + } |
|
iannucci
2015/09/29 04:43:28
ancestor filters are technically equality filters
|
| + if len(q.eqFilts) > allowedEqs { |
| + return fmt.Errorf("kindless queries may not have any equality filters") |
| } |
| for _, o := range q.order { |
| if o.Property != "__key__" || o.Descending { |
| @@ -503,6 +513,28 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
| return ErrNullQuery |
| } |
| } |
| + if q.ineqFiltProp == "__key__" { |
| + if q.ineqFiltLowSet { |
| + if q.ineqFiltLow.Type() != PTKey { |
| + return fmt.Errorf( |
| + "inequality filters on __key__ must use *ds.Key values") |
| + } |
| + if ancestor != nil && !q.ineqFiltLow.Value().(*Key).HasAncestor(ancestor) { |
| + return fmt.Errorf( |
| + "inequality filters on __key__ must be descendants of the __ancestor__") |
| + } |
| + } |
| + if q.ineqFiltHighSet { |
| + if q.ineqFiltHigh.Type() != PTKey { |
| + return fmt.Errorf( |
| + "inequality filters on __key__ must use *ds.Key values") |
| + } |
| + if ancestor != nil && !q.ineqFiltHigh.Value().(*Key).HasAncestor(ancestor) { |
| + return fmt.Errorf( |
| + "inequality filters on __key__ must be descendants of the __ancestor__") |
| + } |
| + } |
| + } |
| } |
| err := error(nil) |
| @@ -527,7 +559,7 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
| kind: q.kind, |
| keysOnly: q.keysOnly, |
| - eventuallyConsistent: q.eventualConsistency || q.eqFilts["__ancestor__"] == nil, |
| + eventuallyConsistent: q.eventualConsistency || ancestor == nil, |
| limit: q.limit, |
| offset: q.offset, |
| start: q.start, |
| @@ -549,14 +581,15 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
| ret.distinct = q.distinct && q.project.Len() > 0 |
| } |
| + seenOrders := stringset.New(len(q.order)) |
|
iannucci
2015/09/29 04:43:28
was getting duplicated orders because the if state
|
| + |
| // if len(q.order) > 0, we already enforce that the first order |
| // is the same as the inequality above. Otherwise we need to add it. |
| if len(q.order) == 0 && q.ineqFiltProp != "" { |
| ret.orders = []IndexColumn{{Property: q.ineqFiltProp}} |
| + seenOrders.Add(q.ineqFiltProp) |
| } |
| - seenOrders := stringset.New(len(q.order)) |
| - |
| // drop orders where there's an equality filter |
| // https://cloud.google.com/appengine/docs/go/datastore/queries#sort_orders_are_ignored_on_properties_with_equality_filters |
| // Deduplicate orders |