dgraph icon indicating copy to clipboard operation
dgraph copied to clipboard

UID query response shows bad data + data type

Open jostillmanns opened this issue 9 months ago • 3 comments

Describe the bug

Given a non-list relation hostType->nestingType, when updating that relation multiple times, the query response for the relation starts to give bad results. The result type for uid is a list of uids and uids internal to that list are previous relationships of hostType->nestingType

Example Query response: {"result":[{"uid":"0x53","nestingType":{"uid":["0x4f","0x50"]}}]}

To Reproduce

Run this test:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"testing"
	"time"

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

func Test_it_correctly_yields_uid_field(t *testing.T) {
	conn, err := grpc.NewClient("localhost:9080", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("conntect: %v", err)
	}

	dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))

	schema := `
type nestingType {
  nestingType.createdAt
}

type hostType {
  hostType.createdAt
  hostType.nestingType
}

nestingType.createdAt: dateTime .
hostType.createdAt: dateTime .
hostType.nestingType: uid @reverse .
`

	err = dgraphClient.Alter(context.Background(), &api.Operation{DropAll: true})
	require.NoError(t, err)

	err = dgraphClient.Alter(context.Background(), &api.Operation{Schema: schema})
	require.NoError(t, err)

	createCmd, err := json.Marshal([]map[string]any{
		{"dgraph.type": "nestingType", "uid": "_:probe0", "nestingType.createdAt": time.Time{}},
		{"dgraph.type": "nestingType", "uid": "_:probe1", "nestingType.createdAt": time.Time{}},
		{"dgraph.type": "nestingType", "uid": "_:probe2", "nestingType.createdAt": time.Time{}},
		{"dgraph.type": "nestingType", "uid": "_:probe3", "nestingType.createdAt": time.Time{}},
	})
	require.NoError(t, err)

	resp, err := dgraphClient.NewTxn().Mutate(context.Background(), &api.Mutation{SetJson: createCmd, CommitNow: true})
	require.NoError(t, err)

	uids := make([]uint64, 4)
	for i := range uids {
		var err error
		uids[i], err = strconv.ParseUint(resp.Uids[fmt.Sprintf("probe%d", i)], 0, 64)
		require.NoError(t, err)
	}

	createCmd, err = json.Marshal([]map[string]any{
		{"dgraph.type": "hostType", "hostType.createdAt": time.Time{}, "hostType.nestingType": map[string]any{"uid": uids[0]}, "uid": "_:probe"},
	})
	require.NoError(t, err)

	resp, err = dgraphClient.NewTxn().Mutate(context.Background(), &api.Mutation{SetJson: createCmd, CommitNow: true})
	require.NoError(t, err)

	hostTypeID := resp.Uids["probe"]

	for _, uid := range uids[1:] {
		txn := dgraphClient.NewTxn()

		q := `query { result(func: uid(%s)) { uid, nestingType: hostType.nestingType { uid }}}`

		queryResp, err := txn.Query(context.Background(), fmt.Sprintf(q, hostTypeID))
		require.NoError(t, err)

		var queryResponse map[string]any
		require.NoError(t, json.Unmarshal(queryResp.Json, &queryResponse))

		require.Equal(t, reflect.String, reflect.TypeOf(queryResponse["result"].([]any)[0].(map[string]any)["nestingType"].(map[string]any)["uid"]).Kind(), string(queryResp.Json))

		updateCmd, err := json.Marshal([]map[string]any{{
			"uid":                  hostTypeID,
			"hostType.nestingType": map[string]any{"uid": uid},
		}})
		require.NoError(t, err)

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

		require.NoError(t, txn.Commit(context.Background()))
	}
}

Expected behavior

  • require.Equal(t, reflect.String, reflect.TypeOf(queryResponse["result"].([]any)[0].(map[string]any)["nestingType"].(map[string]any)["uid"]).Kind(), string(queryResp.Json)) should never fail.
  • query for uid should always be a string (hex value)
  • query for uid should not yield non-valida data (uid for old relationships)

Environment

  • Version: v24.1.2
  • Alpha flags: dgraph alpha --zero dgx-testing-zero:5080 --security "whitelist=0.0.0.0/0" --my dgx-testing-alpha:7080
  • Zero flags: zero --my=dgx-testing-zero:5080

Additional context

I discovered this issue when trying to migrate to v24.1.2 . We had seen this issue with v23 as well, but could never reproduce it. With v24 I am able to consistently reproduce the issue with the above test.

jostillmanns avatar May 13 '25 12:05 jostillmanns

This is similar to the issue described in https://discuss.hypermode.com/t/inconsistent-query-result/19844/8. A fix (https://github.com/hypermodeinc/dgraph/pull/9378) for this has been merged but has not been released yet. You can check if this fixes your problem by trying the nightly docker image or building from source.

xqqp avatar May 13 '25 13:05 xqqp

can confirm, that https://github.com/hypermodeinc/dgraph/pull/9378 fixes the issue 👍

jostillmanns avatar May 13 '25 14:05 jostillmanns