Skip to content

nodes aren't ordered correctly if the query+mutate are in the same txn #5937

@jostillmanns

Description

@jostillmanns

What version of Dgraph are you using?

v20.03.1

Have you tried reproducing the issue with the latest release?

no

Steps to reproduce the issue (command/config used to run Dgraph).

run this test:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"testing"

	"github.com/dgraph-io/dgo/v2"
	"github.com/dgraph-io/dgo/v2/protos/api"
	"github.com/stretchr/testify/require"
	"google.golang.org/grpc"
)

func Test_it_orders_correctly_after_update(t *testing.T) {
	conn, err := grpc.Dial(dgraphAddr(), grpc.WithInsecure())
	if err != nil {
		t.Fatalf("conntect: %v", err)
	}

	dg := dgo.NewDgraphClient(api.NewDgraphClient(conn))
	defer dg.Alter(context.Background(), &api.Operation{DropAll: true})

	schema := `
type node {
  node.order: int
  node.children: [uid]
}

node.order: int .
node.children: [uid] .
`
	err = dg.Alter(context.Background(), &api.Operation{Schema: schema})
	require.NoError(t, err)

	type Node struct {
		ID   string `json:"uid"`
		Type string `json:"dgraph.type"`

		Order    int    `json:"node.order"`
		Children []Node `json:"node.children"`
	}

	in := Node{
		ID:   "_:probe",
		Type: "node",
		Children: []Node{
			{
				Type:  "node",
				Order: 1,
			},
			{
				Type:  "node",
				Order: 2,
			},
			{
				Type:  "node",
				Order: 3,
			},
		},
	}

	js, err := json.Marshal(in)
	require.NoError(t, err)

	mutateResp, err := dg.NewTxn().Mutate(context.Background(), &api.Mutation{SetJson: js, CommitNow: true})
	require.NoError(t, err)

	q := `
query {
  nodes (func: uid(%s)) {
    uid
    node.children (orderasc: node.order) {
      uid
      node.order
    }
  }
}
`
	resp, err := dg.NewTxn().Query(context.Background(), fmt.Sprintf(q, mutateResp.Uids["probe"]))
	require.NoError(t, err)

	var res struct {
		Nodes []Node `json:"nodes"`
	}
	err = json.Unmarshal(resp.GetJson(), &res)
	require.NoError(t, err)

	txn := dg.NewTxn()

	delete, err := json.Marshal(map[string]interface{}{"uid": res.Nodes[0].ID, "node.childen": nil})
	require.NoError(t, err)

	_, err = txn.Mutate(context.Background(), &api.Mutation{DeleteJson: delete})
	require.NoError(t, err)

	update, err := json.Marshal(Node{
		ID: res.Nodes[0].ID,
		Children: []Node{
			{ID: res.Nodes[0].Children[2].ID, Order: 1},
			{ID: res.Nodes[0].Children[1].ID, Order: 2},
			{ID: res.Nodes[0].Children[0].ID, Order: 3},
		},
	})
	require.NoError(t, err)

	_, err = txn.Mutate(context.Background(), &api.Mutation{SetJson: update})

	resp, err = txn.Query(context.Background(), fmt.Sprintf(q, res.Nodes[0].ID))
	require.NoError(t, err)

	err = txn.Commit(context.Background())
	require.NoError(t, err)

	var postUpdate struct {
		Nodes []Node `json:"nodes"`
	}
	err = json.Unmarshal(resp.GetJson(), &postUpdate)
	require.NoError(t, err)

	require.Equal(t, 1, postUpdate.Nodes[0].Children[0].Order) // <- THIS FAILS
}

Expected behaviour and actual result.

the nodes referenced by node.children should be sorted correctly post .Mutate(), however the query yields nodes in incorrect order. I suspect this is because of the query being in the same txn as the .Mutate() statements, as the query shows a correct order outside of the txn.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions