1-to-1 relation overwrite in transaction doesn't work anymore

Moved from GitHub dgraph/5017

Posted by emile-tawfik:

The issue

In v1.1.x with introduction of single relations, the only way to overwrite a single relation was to use multiple mutation in single transaction (delete + insert) (Allow node reference replacements on 1-to-1 relationships · Issue #4136 · dgraph-io/dgraph · GitHub).
However, it seems this method doesn’t work anymore since v1.2.2 because of a bug.

What version of Dgraph are you using?

The issue exists on v1.2.2 and master.
The issue doesn’t exist on v1.2.1

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

There is a test I wrote to reproduce the issue. I added it in query/query4_test.go.

func TestOverwriteOneToOneRelationInATransaction(t *testing.T) {
	schema := `
		onetoonerel: uid .
		data: int .
	`
	setSchema(schema)

	triples := `
		_:node1 <onetoonerel> _:node2 .
		_:node2 <data> "42" .
	`
	resp, err := client.NewTxn().Mutate(context.Background(), &api.Mutation{
		SetNquads: []byte(triples),
		CommitNow: true,
	})
	require.NoError(t, err)

	node1Uid := resp.Uids["node1"]
	node2Uid := resp.Uids["node2"]

	txn := client.NewTxn()

	_, err = txn.Mutate(context.Background(), &api.Mutation{
		DelNquads: []byte(fmt.Sprintf("<%s> <onetoonerel> <%s> .", node1Uid, node2Uid)),
	})
	require.NoError(t, err)

	resp, err = txn.Mutate(context.Background(), &api.Mutation{
		SetNquads: []byte(fmt.Sprintf(`<%s> <onetoonerel> _:node3 .
		_:node3 <data> "24" .`, node1Uid)),
	})
	require.NoError(t, err)

	node3Uid := resp.Uids["node3"]
	err = txn.Commit(context.Background())
	require.NoError(t, err)

	query := fmt.Sprintf(`{
		me(func:uid(%s)) {
			uid
			onetoonerel {
				uid
			}
		}
	}`, node1Uid)
	js := processQueryNoErr(t, query)
	require.JSONEq(t, fmt.Sprintf(`
	{
		"data": {
			"me": [
				{
					"uid": "%s",
					"onetoonerel": {
						"uid": "%s"
					}
				}
			]
		}
	}
	`, node1Uid, node3Uid), js)
}

Expected behaviour and actual result.

After a bisect it seems that the bug was introduced in Overwrite values for uid predicates (#4883) · dgraph-io/dgraph@cc495fc · GitHub

Expected the test to pass.
Got:

--- FAIL: TestOverwriteOneToOneRelationInATransaction (1.07s)
    query4_test.go:1596: 
                Error Trace:    query4_test.go:1596
                Error:          Not equal: 
                                expected: map[string]interface {}{"data":map[string]interface {}{"me":[]interface {}{map[string]interface {}{"onetoonerel":map[string]interface {}{"uid":"0x186bf"}, "uid":"0x186bd"}}}}
                                actual  : map[string]interface {}{"data":map[string]interface {}{"me":[]interface {}{map[string]interface {}{"onetoonerel":map[string]interface {}{"uid":[]interface {}{"0x186be", "0x186bf"}}, "uid":"0x186bd"}}}}
                            
                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -5,3 +5,6 @@
                                     (string) (len=11) "onetoonerel": (map[string]interface {}) (len=1) {
                                -     (string) (len=3) "uid": (string) (len=7) "0x186bf"
                                +     (string) (len=3) "uid": ([]interface {}) (len=2) {
                                +      (string) (len=7) "0x186be",
                                +      (string) (len=7) "0x186bf"
                                +     }
                                     },
                Test:           TestOverwriteOneToOneRelationInATransaction

aakside commented :

I’m looking into this.

martinmr commented :

I will look into this. But in version 1.2.2 you should be able to overwrite the value with a single set. Can you try doing just the set instead of delete+ set? You don’t need the delete anymore. I’ll check the documentation to see if that’s been updated.

There are tests for this use case but I am guessing there are no tests for the old workflow (delete + add).

This is fixed by this PR: fix(Dgraph): fix bug when deleting and adding to a single UID predicate in the same transaction. by martinmr · Pull Request #6431 · dgraph-io/dgraph · GitHub

We have released Dgraph v1.2.8 that has the fix for this issue