func curs(pairs ...interface{}) queryCursor { if len(pairs)%2 != 0 { panic("curs() takes only even pairs") } pre := &bytes.Buffer{} if _, err := cmpbin.WriteUint(pre, uint64(len(pairs)/2)); err != nil { panic(err) } post := serialize.Invertible(&bytes.Buffer{}) for i := 0; i < len(pairs); i += 2 { k, v := pairs[i].(string), pairs[i+1] col, err := dstore.ParseIndexColumn(k) if err != nil { panic(err) } post.SetInvert(col.Descending) if err := serialize.WriteIndexColumn(pre, col); err != nil { panic(err) } if err := serialize.WriteProperty(post, serialize.WithoutContext, prop(v)); err != nil { panic(err) } } return queryCursor(serialize.Join(pre.Bytes(), post.Bytes())) }
func executeQuery(fq *ds.FinalizedQuery, aid, ns string, isTxn bool, idx, head *memStore, cb ds.RawRunCB) error { rq, err := reduce(fq, aid, ns, isTxn) if err == ds.ErrNullQuery { return nil } if err != nil { return err } idxs, err := getIndexes(rq, idx) if err == ds.ErrNullQuery { return nil } if err != nil { return err } strategy := pickQueryStrategy(fq, rq, cb, head) if strategy == nil { // e.g. the normalStrategy found that there were NO entities in the current // namespace. return nil } offset, _ := fq.Offset() limit, hasLimit := fq.Limit() cursorPrefix := []byte(nil) getCursorFn := func(suffix []byte) func() (ds.Cursor, error) { return func() (ds.Cursor, error) { if cursorPrefix == nil { buf := &bytes.Buffer{} _, err := cmpbin.WriteUint(buf, uint64(len(rq.suffixFormat))) memoryCorruption(err) for _, col := range rq.suffixFormat { err := serialize.WriteIndexColumn(buf, col) memoryCorruption(err) } cursorPrefix = buf.Bytes() } // TODO(riannucci): Do we need to decrement suffix instead of increment // if we're sorting by __key__ DESCENDING? return queryCursor(serialize.Join(cursorPrefix, increment(suffix))), nil } } return multiIterate(idxs, func(suffix []byte) error { if offset > 0 { offset-- return nil } if hasLimit { if limit <= 0 { return ds.Stop } limit-- } rawData, decodedProps := parseSuffix(aid, ns, rq.suffixFormat, suffix, -1) keyProp := decodedProps[len(decodedProps)-1] if keyProp.Type() != ds.PTKey { impossible(fmt.Errorf("decoded index row doesn't end with a Key: %#v", keyProp)) } return strategy.handle( rawData, decodedProps, keyProp.Value().(*ds.Key), getCursorFn(suffix)) }) }