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 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())) }
func executeQuery(origQ ds.Query, ns string, isTxn bool, idx, head *memStore, cb ds.RawRunCB) error { q := origQ.(*queryImpl) rq, err := q.reduce(ns, isTxn) if err == errQueryDone { return nil } if err != nil { return err } idxs, err := getIndexes(rq, idx) if err == errQueryDone { return nil } if err != nil { return err } strategy := pickQueryStrategy(q, rq, cb, head) if strategy == nil { // e.g. the normalStrategy found that there were NO entities in the current // namespace. return nil } offset := q.offset limit := q.limit hasLimit := q.limitSet && limit >= 0 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(bjoin(cursorPrefix, increment(suffix))), nil } } multiIterate(idxs, func(suffix []byte) bool { if offset > 0 { offset-- return true } if hasLimit { if limit <= 0 { return false } limit-- } rawData, decodedProps := parseSuffix(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)) }) return nil }