Skip to content

Commit

Permalink
Merge pull request #597 from okp4/feat/add-query-limit
Browse files Browse the repository at this point in the history
Feat/add query limit
  • Loading branch information
ccamel authored Mar 12, 2024
2 parents 4cb0ea6 + 251068f commit ac8bc74
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 76 deletions.
1 change: 1 addition & 0 deletions docs/proto/logic.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ QueryServiceAskRequest is request type for the QueryService/Ask RPC method.
| ----- | ---- | ----- | ----------- |
| `program` | [string](#string) | | program is the logic program to be queried. |
| `query` | [string](#string) | | query is the query string to be executed. |
| `limit` | [string](#string) | | limit specifies the maximum number of solutions to be returned. This field is governed by max_result_count, which defines the upper limit of results that may be requested per query. If this field is not explicitly set, a default value of 1 is applied. |

<a name="logic.v1beta2.QueryServiceAskResponse"></a>

Expand Down
8 changes: 8 additions & 0 deletions proto/logic/v1beta2/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ message QueryServiceAskRequest {
string program = 1 [(gogoproto.moretags) = "yaml:\"program\",omitempty"];
// query is the query string to be executed.
string query = 2 [(gogoproto.moretags) = "yaml:\"query\",omitempty"];
// limit specifies the maximum number of solutions to be returned. This field is governed by
// max_result_count, which defines the upper limit of results that may be requested per query.
// If this field is not explicitly set, a default value of 1 is applied.
string limit = 3 [
(gogoproto.moretags) = "yaml:\"limit\",omitempty",
(gogoproto.customtype) = "cosmossdk.io/math.Uint",
(gogoproto.nullable) = true
];
}

// QueryServiceAskResponse is response type for the QueryService/Ask RPC method.
Expand Down
1 change: 0 additions & 1 deletion proto/logic/v1beta2/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ message Answer {
bool has_more = 2 [(gogoproto.moretags) = "yaml:\"has_more\",omitempty"];
// variables represent all the variables in the query.
repeated string variables = 3 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"variables\",omitempty"
];
// results represent all the results of the query.
Expand Down
7 changes: 6 additions & 1 deletion x/logic/keeper/grpc_query_ask.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import (
goctx "context"

errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/okp4/okp4d/v7/x/logic/meter"
"github.com/okp4/okp4d/v7/x/logic/types"
"github.com/okp4/okp4d/v7/x/logic/util"
)

var defaultLimits = sdkmath.OneUint()

func (k Keeper) Ask(ctx goctx.Context, req *types.QueryServiceAskRequest) (response *types.QueryServiceAskResponse, err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)

Expand Down Expand Up @@ -43,7 +47,8 @@ func (k Keeper) Ask(ctx goctx.Context, req *types.QueryServiceAskRequest) (respo
return k.execute(
sdkCtx,
req.Program,
req.Query)
req.Query,
util.DerefOrDefault(req.Limit, defaultLimits))
}

// withGasMeter returns a new context with a gas meter that has the given limit.
Expand Down
63 changes: 50 additions & 13 deletions x/logic/keeper/grpc_query_ask_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:gocognit
package keeper_test

import (
Expand Down Expand Up @@ -33,6 +34,7 @@ func TestGRPCAsk(t *testing.T) {
program string
query string
limit int
maxResultCount int
predicateBlacklist []string
maxGas uint64
predicateCosts map[string]uint64
Expand Down Expand Up @@ -83,9 +85,22 @@ func TestGRPCAsk(t *testing.T) {
},
},
{
program: "father(bob, alice). father(bob, john).",
query: "father(bob, X).",
limit: 5,
program: "father(bob, alice). father(bob, john).",
query: "father(bob, X).",
maxResultCount: 5,
expectedAnswer: &types.Answer{
HasMore: true,
Variables: []string{"X"},
Results: []types.Result{{Substitutions: []types.Substitution{{
Variable: "X", Expression: "alice",
}}}},
},
},
{
program: "father(bob, alice). father(bob, john).",
query: "father(bob, X).",
limit: 2,
maxResultCount: 5,
expectedAnswer: &types.Answer{
Variables: []string{"X"},
Results: []types.Result{{Substitutions: []types.Substitution{{
Expand All @@ -95,6 +110,19 @@ func TestGRPCAsk(t *testing.T) {
}}}},
},
},
{
program: "father(bob, alice). father(bob, john).",
query: "father(bob, X).",
limit: 2,
maxResultCount: 1,
expectedAnswer: &types.Answer{
HasMore: true,
Variables: []string{"X"},
Results: []types.Result{{Substitutions: []types.Substitution{{
Variable: "X", Expression: "alice",
}}}},
},
},
{
query: "block_height(X).",
expectedAnswer: &types.Answer{
Expand Down Expand Up @@ -204,8 +232,8 @@ foo(a2).
foo(a3) :- throw(error(resource_error(foo))).
foo(a4).
`,
query: `foo(X).`,
limit: 1,
query: `foo(X).`,
maxResultCount: 1,
expectedAnswer: &types.Answer{
HasMore: true,
Variables: []string{"X"},
Expand All @@ -221,8 +249,9 @@ foo(a2).
foo(a3) :- throw(error(resource_error(foo))).
foo(a4).
`,
query: `foo(X).`,
limit: 2,
query: `foo(X).`,
limit: 2,
maxResultCount: 3,
expectedAnswer: &types.Answer{
HasMore: true,
Variables: []string{"X"},
Expand All @@ -239,8 +268,9 @@ foo(a2).
foo(a3) :- throw(error(resource_error(foo))).
foo(a4).
`,
query: `foo(X).`,
limit: 3,
query: `foo(X).`,
limit: 5,
maxResultCount: 3,
expectedAnswer: &types.Answer{
Variables: []string{"X"},
Results: []types.Result{
Expand All @@ -257,8 +287,9 @@ foo(a2).
foo(a3) :- throw(error(resource_error(foo))).
foo(a4).
`,
query: `foo(X).`,
limit: 5,
query: `foo(X).`,
limit: 5,
maxResultCount: 5,
expectedAnswer: &types.Answer{
Variables: []string{"X"},
Results: []types.Result{
Expand Down Expand Up @@ -295,9 +326,9 @@ foo(a4).
return fsProvider
},
)
limit := sdkmath.NewUint(uint64(lo.If(tc.limit == 0, 1).Else(tc.limit)))
maxResultCount := sdkmath.NewUint(uint64(lo.If(tc.maxResultCount == 0, 1).Else(tc.maxResultCount)))
params := types.DefaultParams()
params.Limits.MaxResultCount = &limit
params.Limits.MaxResultCount = &maxResultCount
if tc.predicateBlacklist != nil {
params.Interpreter.PredicatesFilter.Blacklist = tc.predicateBlacklist
}
Expand Down Expand Up @@ -326,9 +357,15 @@ foo(a4).

queryClient := types.NewQueryServiceClient(queryHelper)

var limit *sdkmath.Uint
if tc.limit != 0 {
v := sdkmath.NewUint(uint64(tc.limit))
limit = &v
}
query := types.QueryServiceAskRequest{
Program: tc.program,
Query: tc.query,
Limit: limit,
}

Convey("when the grpc query ask is called", func() {
Expand Down
4 changes: 2 additions & 2 deletions x/logic/keeper/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (k Keeper) enhanceContext(ctx context.Context) context.Context {
return sdkCtx
}

func (k Keeper) execute(ctx context.Context, program, query string) (*types.QueryServiceAskResponse, error) {
func (k Keeper) execute(ctx context.Context, program, query string, limit sdkmath.Uint) (*types.QueryServiceAskResponse, error) {
ctx = k.enhanceContext(ctx)
sdkCtx := sdk.UnwrapSDKContext(ctx)
limits := k.limits(sdkCtx)
Expand All @@ -53,7 +53,7 @@ func (k Keeper) execute(ctx context.Context, program, query string) (*types.Quer
return nil, errorsmod.Wrapf(types.InvalidArgument, "error compiling query: %v", err.Error())
}

answer, err := k.queryInterpreter(ctx, i, query, *limits.MaxResultCount)
answer, err := k.queryInterpreter(ctx, i, query, sdkmath.MinUint(limit, *limits.MaxResultCount))
if err != nil {
return nil, errorsmod.Wrapf(types.InvalidArgument, "error executing query: %v", err.Error())
}
Expand Down
126 changes: 93 additions & 33 deletions x/logic/types/query.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ac8bc74

Please sign in to comment.