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 |