Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GQL variables and operation name #2993

Merged
merged 8 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions cli/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
package cli

import (
"encoding/json"
"io"
"os"

"github.com/spf13/cobra"

"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/errors"
)

Expand All @@ -26,6 +28,8 @@

func MakeRequestCommand() *cobra.Command {
var filePath string
var operationName string
var variablesJSON string
var cmd = &cobra.Command{
Use: "query [-i --identity] [request]",
Short: "Send a DefraDB GraphQL query request",
Expand Down Expand Up @@ -70,8 +74,21 @@
return errors.New("request cannot be empty")
}

var options []client.RequestOption
if variablesJSON != "" {
var variables map[string]any
err := json.Unmarshal([]byte(variablesJSON), &variables)
if err != nil {
return err

Check warning on line 82 in cli/request.go

View check run for this annotation

Codecov / codecov/patch

cli/request.go#L82

Added line #L82 was not covered by tests
}
options = append(options, client.WithVariables(variables))
}
if operationName != "" {
options = append(options, client.WithOperationName(operationName))
}

store := mustGetContextStore(cmd)
result := store.ExecRequest(cmd.Context(), request)
result := store.ExecRequest(cmd.Context(), request, options...)

var errors []string
for _, err := range result.GQL.Errors {
Expand All @@ -88,7 +105,8 @@
return nil
},
}

cmd.Flags().StringVarP(&operationName, "operation", "o", "", "Name of the operation to execute in the query")
cmd.Flags().StringVarP(&variablesJSON, "variables", "v", "", "JSON encoded variables to use in the query")
cmd.Flags().StringVarP(&filePath, "file", "f", "", "File containing the query request")
return cmd
}
27 changes: 26 additions & 1 deletion client/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,32 @@ type Store interface {
GetAllIndexes(context.Context) (map[CollectionName][]IndexDescription, error)

// ExecRequest executes the given GQL request against the [Store].
ExecRequest(ctx context.Context, request string) *RequestResult
ExecRequest(ctx context.Context, request string, opts ...RequestOption) *RequestResult
}

// GQLOptions contains optional arguments for GQL requests.
type GQLOptions struct {
// OperationName is the name of the operation to exec.
OperationName string
// Variables is a map of names to varible values.
Variables map[string]any
}

// RequestOption sets an optional request setting.
type RequestOption func(*GQLOptions)

// WithOperationName sets the operation name for a GQL request.
func WithOperationName(operationName string) RequestOption {
return func(o *GQLOptions) {
o.OperationName = operationName
}
}

// WithVariables sets the variables for a GQL request.
func WithVariables(variables map[string]any) RequestOption {
return func(o *GQLOptions) {
o.Variables = variables
}
}

// GQLResult represents the immediate results of a GQL request.
Expand Down
35 changes: 25 additions & 10 deletions client/mocks/db.go

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

6 changes: 4 additions & 2 deletions docs/website/references/cli/defradb_client_query.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ defradb client query [-i --identity] [request] [flags]
### Options

```
-f, --file string File containing the query request
-h, --help help for query
-f, --file string File containing the query request
-h, --help help for query
-o, --operation string Name of the operation to execute in the query
-v, --variables string JSON encoded variables to use in the query
```

### Options inherited from parent commands
Expand Down
7 changes: 7 additions & 0 deletions docs/website/references/http/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,15 @@
},
"graphql_request": {
"properties": {
"operationName": {
"type": "string"
},
"query": {
"type": "string"
},
"variables": {
"additionalProperties": {},
"type": "object"
}
},
"type": "object"
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/sourcenetwork/defradb

go 1.22

toolchain go1.22.0

require (
github.com/bits-and-blooms/bitset v1.14.2
github.com/bxcodec/faker v2.0.1+incompatible
Expand Down Expand Up @@ -45,7 +47,7 @@ require (
github.com/sourcenetwork/badger/v4 v4.2.1-0.20231113215945-a63444ca5276
github.com/sourcenetwork/corelog v0.0.8
github.com/sourcenetwork/go-libp2p-pubsub-rpc v0.0.14
github.com/sourcenetwork/graphql-go v0.7.10-0.20231113214537-a9560c1898dd
github.com/sourcenetwork/graphql-go v0.7.10-0.20240910200541-550a51c57c7d
github.com/sourcenetwork/immutable v0.3.0
github.com/sourcenetwork/sourcehub v0.2.1-0.20240704194128-f43f5e427274
github.com/spf13/cobra v1.8.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1396,8 +1396,8 @@ github.com/sourcenetwork/corelog v0.0.8 h1:jCo0mFBpWrfhUCGzzN3uUtPGyQv3jnITdPO1s
github.com/sourcenetwork/corelog v0.0.8/go.mod h1:cMabHgs3kARgYTQeQYSOmaGGP8XMU6sZrHd8LFrL3zA=
github.com/sourcenetwork/go-libp2p-pubsub-rpc v0.0.14 h1:620zKV4rOn7U5j/WsPkk4SFj0z9/pVV4bBx0BpZQgro=
github.com/sourcenetwork/go-libp2p-pubsub-rpc v0.0.14/go.mod h1:jUoQv592uUX1u7QBjAY4C+l24X9ArhPfifOqXpDHz4U=
github.com/sourcenetwork/graphql-go v0.7.10-0.20231113214537-a9560c1898dd h1:lmpW39/8wPJ0khWRhOcj7Bj0HYKbSmQ8rXMJw1cMB8U=
github.com/sourcenetwork/graphql-go v0.7.10-0.20231113214537-a9560c1898dd/go.mod h1:rkahXkgRH/3vZErN1Bx+qt1+w+CV5fgaJyKKWgISe4U=
github.com/sourcenetwork/graphql-go v0.7.10-0.20240910200541-550a51c57c7d h1:gpBJx/mKmpelxZfHT4AYhPYFgSy8DKp/Ca+bBzIIy2A=
github.com/sourcenetwork/graphql-go v0.7.10-0.20240910200541-550a51c57c7d/go.mod h1:rkahXkgRH/3vZErN1Bx+qt1+w+CV5fgaJyKKWgISe4U=
github.com/sourcenetwork/immutable v0.3.0 h1:gHPtGvLrTBTK5YpDAhMU+u+S8v1F6iYmc3nbZLryMdc=
github.com/sourcenetwork/immutable v0.3.0/go.mod h1:GD7ceuh/HD7z6cdIwzKK2ctzgZ1qqYFJpsFp+8qYnbI=
github.com/sourcenetwork/raccoondb v0.2.1-0.20240606193653-1e91e9be9234 h1:8dA9bVC1A0ChJygtsUfNsek3oR0GnwpLoYpmEo4t2mk=
Expand Down
13 changes: 12 additions & 1 deletion http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,22 @@ func (c *Client) GetAllIndexes(ctx context.Context) (map[client.CollectionName][
func (c *Client) ExecRequest(
ctx context.Context,
query string,
opts ...client.RequestOption,
) *client.RequestResult {
methodURL := c.http.baseURL.JoinPath("graphql")
result := &client.RequestResult{}

body, err := json.Marshal(&GraphQLRequest{query})
gqlOptions := &client.GQLOptions{}
for _, o := range opts {
o(gqlOptions)
}
gqlRequest := &GraphQLRequest{
Query: query,
OperationName: gqlOptions.OperationName,
Variables: gqlOptions.Variables,
}

body, err := json.Marshal(gqlRequest)
if err != nil {
result.GQL.Errors = []error{err}
return result
Expand Down
13 changes: 11 additions & 2 deletions http/handler_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ func (s *storeHandler) PrintDump(rw http.ResponseWriter, req *http.Request) {
}

type GraphQLRequest struct {
Query string `json:"query"`
Query string `json:"query"`
OperationName string `json:"operationName"`
Variables map[string]any `json:"variables"`
}

type GraphQLResponse struct {
Expand Down Expand Up @@ -299,7 +301,14 @@ func (s *storeHandler) ExecRequest(rw http.ResponseWriter, req *http.Request) {
return
}

result := store.ExecRequest(req.Context(), request.Query)
var options []client.RequestOption
if request.OperationName != "" {
options = append(options, client.WithOperationName(request.OperationName))
}
if len(request.Variables) > 0 {
options = append(options, client.WithVariables(request.Variables))
}
result := store.ExecRequest(req.Context(), request.Query, options...)

if result.Subscription == nil {
responseJSON(rw, http.StatusOK, GraphQLResponse{result.GQL.Data, result.GQL.Errors})
Expand Down
2 changes: 1 addition & 1 deletion internal/core/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type Parser interface {
ExecuteIntrospection(request string) *client.RequestResult

// Parses the given request, returning a strongly typed model of that request.
Parse(*ast.Document) (*request.Request, []error)
Parse(*ast.Document, *client.GQLOptions) (*request.Request, []error)

// NewFilterFromString creates a new filter from a string.
NewFilterFromString(collectionType string, body string) (immutable.Option[request.Filter], error)
Expand Down
4 changes: 2 additions & 2 deletions internal/db/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

// execRequest executes a request against the database.
func (db *db) execRequest(ctx context.Context, request string) *client.RequestResult {
func (db *db) execRequest(ctx context.Context, request string, options *client.GQLOptions) *client.RequestResult {
res := &client.RequestResult{}
ast, err := db.parser.BuildRequestAST(request)
if err != nil {
Expand All @@ -29,7 +29,7 @@ func (db *db) execRequest(ctx context.Context, request string) *client.RequestRe
return db.parser.ExecuteIntrospection(request)
}

parsedRequest, errors := db.parser.Parse(ast)
parsedRequest, errors := db.parser.Parse(ast, options)
if len(errors) > 0 {
res.GQL.Errors = errors
return res
Expand Down
9 changes: 7 additions & 2 deletions internal/db/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

// ExecRequest executes a request against the database.
func (db *db) ExecRequest(ctx context.Context, request string) *client.RequestResult {
func (db *db) ExecRequest(ctx context.Context, request string, opts ...client.RequestOption) *client.RequestResult {
ctx, txn, err := ensureContextTxn(ctx, db, false)
if err != nil {
res := &client.RequestResult{}
Expand All @@ -30,7 +30,12 @@ func (db *db) ExecRequest(ctx context.Context, request string) *client.RequestRe
}
defer txn.Discard(ctx)

res := db.execRequest(ctx, request)
options := &client.GQLOptions{}
for _, o := range opts {
o(options)
}

res := db.execRequest(ctx, request, options)
if len(res.GQL.Errors) > 0 {
return res
}
Expand Down
2 changes: 1 addition & 1 deletion internal/db/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (db *db) addView(
return nil, err
}

req, errs := db.parser.Parse(ast)
req, errs := db.parser.Parse(ast, &client.GQLOptions{})
if len(errs) > 0 {
return nil, errors.Join(errs...)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/request/graphql/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (p *parser) ExecuteIntrospection(request string) *client.RequestResult {
return res
}

func (p *parser) Parse(ast *ast.Document) (*request.Request, []error) {
func (p *parser) Parse(ast *ast.Document, options *client.GQLOptions) (*request.Request, []error) {
schema := p.schemaManager.Schema()
validationResult := gql.ValidateDocument(schema, ast, nil)
if !validationResult.IsValid {
Expand All @@ -95,7 +95,7 @@ func (p *parser) Parse(ast *ast.Document) (*request.Request, []error) {
return nil, errors
}

query, parsingErrors := defrap.ParseRequest(*schema, ast)
query, parsingErrors := defrap.ParseRequest(*schema, ast, options)
if len(parsingErrors) > 0 {
return nil, parsingErrors
}
Expand Down
Loading
Loading