Index: service/datastore/query.go |
diff --git a/service/datastore/query.go b/service/datastore/query.go |
index 74ed2f0ec293a21df613bd7a672091dd7a8f4977..85bcb3a18d3a29c684439e2606cb37f601b7313c 100644 |
--- a/service/datastore/query.go |
+++ b/service/datastore/query.go |
@@ -470,14 +470,25 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
return q.finalized, q.err |
} |
+ ancSlice, hasAncestor := q.eqFilts["__ancestor__"] |
+ ancestor := (*Key)(nil) |
+ if hasAncestor { |
+ ancestor = ancSlice[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 hasAncestor { |
+ allowedEqs = 1 |
+ } |
+ 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 +514,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 hasAncestor && !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 hasAncestor && !q.ineqFiltHigh.Value().(*Key).HasAncestor(ancestor) { |
+ return fmt.Errorf( |
+ "inequality filters on __key__ must be descendants of the __ancestor__") |
+ } |
+ } |
+ } |
} |
err := error(nil) |
@@ -527,7 +560,7 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
kind: q.kind, |
keysOnly: q.keysOnly, |
- eventuallyConsistent: q.eventualConsistency || q.eqFilts["__ancestor__"] == nil, |
+ eventuallyConsistent: q.eventualConsistency || !hasAncestor, |
limit: q.limit, |
offset: q.offset, |
start: q.start, |
@@ -549,14 +582,15 @@ func (q *Query) Finalize() (*FinalizedQuery, error) { |
ret.distinct = q.distinct && q.project.Len() > 0 |
} |
+ seenOrders := stringset.New(len(q.order)) |
+ |
// 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 |