func (q *queryImpl) Order(prop string) ds.Query { col := ds.IndexColumn{} return q.checkMutateClone( func() error { // check that first order == first inequality. // if order is an equality already, ignore it col.Property = strings.TrimSpace(prop) if strings.HasPrefix(prop, "-") { col.Direction = ds.DESCENDING col.Property = strings.TrimSpace(prop[1:]) } else if strings.HasPrefix(prop, "+") { return fmt.Errorf("datastore: invalid order: %q", prop) } if len(col.Property) == 0 { return errors.New("datastore: empty order") } if len(q.order) == 0 && q.ineqFilter.prop != "" && q.ineqFilter.prop != col.Property { return fmt.Errorf( "first sort order must match inequality filter: %q v %q", prop, q.ineqFilter.prop) } if q.kind == "" && (col.Property != "__key__" || col.Direction != ds.ASCENDING) { return fmt.Errorf("invalid order for kindless query: %#v", col) } return nil }, func(q *queryImpl) { if _, ok := q.eqFilters[col.Property]; ok { // skip it if it's an equality filter // https://cloud.google.com/appengine/docs/go/datastore/queries#sort_orders_are_ignored_on_properties_with_equality_filters return } for _, order := range q.order { if order.Property == col.Property { // can't sort by the same order twice return } } q.order = append(q.order, col) }) }
func curs(pairs ...interface{}) queryCursor { if len(pairs)%2 != 0 { panic("curs() takes only even pairs") } pre := &bytes.Buffer{} cmpbin.WriteUint(pre, uint64(len(pairs)/2)) post := serialize.Invertible(&bytes.Buffer{}) for i := 0; i < len(pairs); i += 2 { k, v := pairs[i].(string), pairs[i+1] col := dsS.IndexColumn{Property: k} post.SetInvert(false) if k[0] == '-' { post.SetInvert(false) col.Property = k[1:] col.Direction = dsS.DESCENDING } serialize.WriteIndexColumn(pre, col) serialize.WriteProperty(post, serialize.WithoutContext, prop(v)) } return queryCursor(bjoin(pre.Bytes(), post.Bytes())) }