diff --git a/dgraph/cmd/alpha/upsert_test.go b/dgraph/cmd/alpha/upsert_test.go index cf002d19050..012e44614a3 100644 --- a/dgraph/cmd/alpha/upsert_test.go +++ b/dgraph/cmd/alpha/upsert_test.go @@ -17,13 +17,16 @@ package alpha import ( + "context" "fmt" + "sort" "strconv" "strings" "sync" "testing" "github.com/dgraph-io/dgo/v2" + "github.com/dgraph-io/dgo/v2/protos/api" "github.com/dgraph-io/dgraph/testutil" "github.com/stretchr/testify/require" ) @@ -2065,3 +2068,65 @@ upsert { // of vars. require.Equal(t, 0, len(mr.vars)) } + +func TestMultiMutationEmptyRequest(t *testing.T) { + // We are using the dgo client in this test here to test the grpc interface + dg, err := testutil.DgraphClientWithGroot("localhost:9180") + require.NoError(t, err, "error while getting a dgraph client") + + require.NoError(t, dg.Alter(context.Background(), &api.Operation{ + DropOp: api.Operation_ALL, + })) + require.NoError(t, dg.Alter(context.Background(), &api.Operation{ + Schema: ` + name: string @index(exact) . + branch: string . + amount: float . + `, + })) + + req := &api.Request{} + _, err = dg.NewTxn().Do(context.Background(), req) + require.Contains(t, strings.ToLower(err.Error()), "empty request") +} + +// This mutation (upsert) has one independent query and one independent mutation. +func TestMultiMutationNoUpsert(t *testing.T) { + dg, err := testutil.DgraphClientWithGroot("localhost:9180") + require.NoError(t, err, "error while getting a dgraph client") + + require.NoError(t, dg.Alter(context.Background(), &api.Operation{ + DropOp: api.Operation_ALL, + })) + require.NoError(t, dg.Alter(context.Background(), &api.Operation{ + Schema: ` + email: string @index(exact) . + works_for: string @index(exact) . + works_with: [uid] . + `, + })) + + req := &api.Request{ + Query: ` + query { + empty(func: eq(works_for, "company1")) { + uid + name + } + }`, + Mutations: []*api.Mutation{ + &api.Mutation{ + SetNquads: []byte(` + _:user1 "user1" . + _:user1 "user1@company1.io" . + _:user1 "company1" .`), + }, + }, + CommitNow: true, + } + resp, err := dg.NewTxn().Do(context.Background(), req) + require.NoError(t, err) + sort.Strings(resp.Txn.Preds) + require.Equal(t, []string{"1-email", "1-name", "1-works_for"}, resp.Txn.Preds) + testutil.CompareJSON(t, `{"empty": []}`, string(resp.Json)) +} diff --git a/edgraph/server.go b/edgraph/server.go index 179f2b86513..0797933040e 100644 --- a/edgraph/server.go +++ b/edgraph/server.go @@ -522,8 +522,8 @@ func (s *Server) doQuery(ctx context.Context, req *api.Request, authorize int) ( span.Annotatef(nil, "Request received: %v", req) if len(req.Query) == 0 && len(req.Mutations) == 0 { - span.Annotate(nil, "Empty request") - return nil, errors.Errorf("Empty request") + span.Annotate(nil, "empty request") + return nil, errors.Errorf("empty request") } qc := &queryContext{ @@ -544,8 +544,18 @@ func (s *Server) doQuery(ctx context.Context, req *api.Request, authorize int) ( } } - if resp, rerr = processQuery(ctx, qc); rerr != nil { - return + if qc.req.StartTs == 0 { + start := time.Now() + qc.req.StartTs = State.getTimestamp(qc.req.ReadOnly) + qc.latency.AssignTimestamp = time.Since(start) + } + + if qc.req.Query != "" { + if resp, rerr = processQuery(ctx, qc); rerr != nil { + return + } + } else { + resp = &api.Response{} } if isMutation { @@ -588,6 +598,9 @@ func parseRequest(qc *queryContext) error { // updating queries to include dummy variables for conditional upsert upsertQuery := buildUpsertQuery(qc) + if upsertQuery == "" { + return nil + } // parsing the updated query var err error @@ -694,12 +707,6 @@ func processQuery(ctx context.Context, qc *queryContext) (*api.Response, error) qr.Cache = worker.NoCache } - if qc.req.StartTs == 0 { - assignTimestampStart := time.Now() - qc.req.StartTs = State.getTimestamp(qc.req.ReadOnly) - qc.latency.AssignTimestamp = time.Since(assignTimestampStart) - } - qr.ReadTs = qc.req.StartTs resp := &api.Response{} resp.Txn = &api.TxnContext{StartTs: qc.req.StartTs}