Skip to content

Commit

Permalink
search
Browse files Browse the repository at this point in the history
added reverse ordering in search
  • Loading branch information
scottburch committed Sep 20, 2020
1 parent 613047f commit 1699f32
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 0 deletions.
46 changes: 46 additions & 0 deletions x/crud/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command {
GetCmdQRead(storeKey, cdc),
GetCmdQHas(storeKey, cdc),
GetCmdQKeys(storeKey, cdc),
GetCmdQSearch(storeKey, cdc),
GetCmdQKeyValues(storeKey, cdc),
GetCmdQCount(storeKey, cdc),
GetCmdQGetLease(storeKey, cdc),
Expand Down Expand Up @@ -134,6 +135,51 @@ func GetCmdQKeys(queryRoute string, cdc *codec.Codec) *cobra.Command {
}
}

func GetCmdQSearch(queryRoute string, cdc *codec.Codec) *cobra.Command {
reverse := false
cmd := &cobra.Command{
Use: "search [UUID] [prefix] [page] [limit]",
Short: "search UUID prefix [page] [limit]",
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
UUID := args[0]
prefix := args[1]

direction := "asc"
if reverse {
direction = "desc"
}

if len(args) < 3 {
args = append(args, "1")
}

if len(args) < 4 {
args = append(args, "100")
}

page := args[2]
limit := args[3]
res, _, _ := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/search/%s/%s/%s/%s/%s", queryRoute, UUID, prefix, page, limit, direction), nil)

var out types.QueryResultSearch
cdc.MustUnmarshalJSON(res, &out)

// ensure we don't lose the fact that the keyvalues list is empty...
if out.KeyValues == nil {
out.KeyValues = make([]types.KeyValue, 0)
}

return cliCtx.PrintOutput(out)
},
}
cmd.Flags().BoolVar(&reverse, "reverse", false, "Search in descending order")
return cmd

}


func GetCmdQKeyValues(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "keyvalues [UUID]",
Expand Down
11 changes: 11 additions & 0 deletions x/crud/client/rest/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ func BlzQKeysHandler(cliCtx context.CLIContext, storeName string) http.HandlerFu
}
}

func BlzQSearchHandler(cliCtx context.CLIContext, storeName string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)

res, _, _ := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/search/%s/%s/%s/%s/%s", storeName, vars["UUID"], vars["prefix"], vars["page"], vars["limit"], vars["direction"]), nil)

rest.PostProcessResponse(w, cliCtx, res)
}
}


func BlzQKeyValuesHandler(cliCtx context.CLIContext, storeName string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
Expand Down
1 change: 1 addition & 0 deletions x/crud/client/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, storeName string)
r.HandleFunc(fmt.Sprintf("/%s/has/{UUID}/{key}", storeName), BlzQHasHandler(cliCtx, storeName)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/keys", storeName), BlzKeysHandler(cliCtx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/%s/keys/{UUID}", storeName), BlzQKeysHandler(cliCtx, storeName)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/search/{UUID}/{prefix}/{page}/{limit}/{direction}", storeName), BlzQSearchHandler(cliCtx, storeName)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/keyvalues", storeName), BlzKeyValuesHandler(cliCtx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/%s/keyvalues/{UUID}", storeName), BlzQKeyValuesHandler(cliCtx, storeName)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/multiupdate", storeName), BlzMultiUpdateHandler(cliCtx)).Methods("POST")
Expand Down
45 changes: 45 additions & 0 deletions x/crud/internal/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
"sort"
"strconv"
cosmosTypes "github.com/cosmos/cosmos-sdk/store/types"
)

type MaxKeeperSizes struct {
Expand All @@ -40,6 +41,7 @@ type IKeeper interface {
GetCount(ctx sdk.Context, store sdk.KVStore, UUID string, owner sdk.AccAddress) types.QueryResultCount
GetDefaultLeaseBlocks() int64
GetKVStore(ctx sdk.Context) sdk.KVStore
Search(ctx sdk.Context, store sdk.KVStore, UUID string, prefix string, page, limit uint, direction string, owner sdk.AccAddress) types.QueryResultKeyValues
GetKeyValues(ctx sdk.Context, store sdk.KVStore, UUID string, owner sdk.AccAddress) types.QueryResultKeyValues
GetKeys(ctx sdk.Context, store sdk.KVStore, UUID string, owner sdk.AccAddress) types.QueryResultKeys
GetLeaseStore(ctx sdk.Context) sdk.KVStore
Expand Down Expand Up @@ -190,6 +192,49 @@ func (k Keeper) GetCdc() *codec.Codec {
return k.cdc
}

func (k Keeper) Search(ctx sdk.Context, store sdk.KVStore, UUID string, searchPrefix string, page, limit uint, direction string, owner sdk.AccAddress) types.QueryResultKeyValues {
prefix := UUID + "\x00" + searchPrefix
var iterator sdk.Iterator

if direction == "desc" {
// TODO: change this to be sdk instead of cosmosTypes after cosmos-sdk is fixed
iterator = cosmosTypes.KVStoreReversePrefixIteratorPaginated(store, []byte(prefix), page, limit)
} else {
iterator = sdk.KVStorePrefixIteratorPaginated(store, []byte(prefix), page, limit)
}
defer iterator.Close()

keyValues := types.QueryResultKeyValues{UUID: UUID, KeyValues: make([]types.KeyValue, 0)}

keyValuesSize := uint64(0)

for ; iterator.Valid(); iterator.Next() {
var bz = store.Get(iterator.Key())
var value types.BLZValue
k.cdc.MustUnmarshalBinaryBare(bz, &value)

if owner == nil || value.Owner.Equals(owner) {
key := string(iterator.Key())[len(UUID) + 1:]
keyValuesSize = keyValuesSize + uint64(len(key)) + uint64(len(value.Value))

if ctx.GasMeter().IsPastLimit() {
return types.QueryResultKeyValues{UUID: UUID, KeyValues: make([]types.KeyValue, 0)}
}

if keyValuesSize < k.mks.MaxKeyValuesSize {
keyValues.KeyValues = append(keyValues.KeyValues, types.KeyValue{
Key: key,
Value: value.Value,
})
} else {
return keyValues
}
}
}
return keyValues
}


func (k Keeper) GetKeyValues(ctx sdk.Context, store sdk.KVStore, UUID string, owner sdk.AccAddress) types.QueryResultKeyValues {
prefix := UUID + "\x00"
iterator := sdk.KVStorePrefixIterator(store, []byte(prefix))
Expand Down
15 changes: 15 additions & 0 deletions x/crud/internal/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
QueryRead = "read"
QueryHas = "has"
QueryKeys = "keys"
QuerySearch = "search"
QueryKeyValues = "keyvalues"
QueryCount = "count"
QueryGetLease = "getlease"
Expand All @@ -45,6 +46,8 @@ func NewQuerier(keeper IKeeper) sdk.Querier {
return queryHas(ctx, path[1:], req, keeper, keeper.GetCdc())
case QueryKeys:
return queryKeys(ctx, path[1:], req, keeper, keeper.GetCdc())
case QuerySearch:
return querySearch(ctx, path[1:], req, keeper, keeper.GetCdc())
case QueryKeyValues:
return queryKeyValues(ctx, path[1:], req, keeper, keeper.GetCdc())
case QueryCount:
Expand Down Expand Up @@ -110,6 +113,18 @@ func queryKeys(ctx sdk.Context, path []string, _ abci.RequestQuery, keeper IKeep
return res, nil
}

func querySearch(ctx sdk.Context, path []string, _ abci.RequestQuery, keeper IKeeper, cdc *codec.Codec) ([]byte, error) {
page, _ := strconv.ParseUint(path[2], 10, 64)
limit, _ := strconv.ParseUint(path[3], 10, 64)

res, err := codec.MarshalJSONIndent(cdc, keeper.Search(ctx, keeper.GetKVStore(ctx), path[0], path[1], uint(page), uint(limit), path[4], nil))
if err != nil {
panic("could not marshal result to JSON")
}

return res, nil
}

func queryKeyValues(ctx sdk.Context, path []string, _ abci.RequestQuery, keeper IKeeper, cdc *codec.Codec) ([]byte, error) {
res, err := codec.MarshalJSONIndent(cdc, keeper.GetKeyValues(ctx, keeper.GetKVStore(ctx), path[0], nil))
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions x/crud/internal/types/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ type QueryResultKeyValues struct {
KeyValues []KeyValue `json:"keyvalues"`
}

type QueryResultSearch struct {
UUID string `json:"uuid"`
KeyValues []KeyValue `json:"keyvalues"`
}

type QueryResultCount struct {
UUID string `json:"uuid"`
Count uint64 `json:"count,string"`
Expand Down

0 comments on commit 1699f32

Please sign in to comment.