diff --git a/mutate.go b/mutate.go index ead6dd9..80d115f 100644 --- a/mutate.go +++ b/mutate.go @@ -76,12 +76,12 @@ func (c client) process(ctx context.Context, return fmt.Errorf("failed to get current schema: %w", err) } - // Get the type name from the object - schemaObjVal := reflect.ValueOf(schemaObj) - if schemaObjVal.Kind() == reflect.Ptr { - schemaObjVal = schemaObjVal.Elem() - } - typeName := schemaObjVal.Type().Name() + // Resolve the Dgraph type name the same way mutations and schema + // generation do (the DType tag, falling back to the Go struct name). + // Using the raw Go struct name here would reject types whose Dgraph + // name differs from the struct name, e.g. a `migrationLock` struct + // declared as `dgraph:"MigrationLock"`. + typeName := getNodeType(schemaObj) // When AutoSchema is disabled, validate that required schema exists // Fail if user schema for the type doesn't exist, even if only system schema exists diff --git a/mutate_dtype_validation_test.go b/mutate_dtype_validation_test.go new file mode 100644 index 0000000..842c388 --- /dev/null +++ b/mutate_dtype_validation_test.go @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: © 2017-2026 Istari Digital, Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +package modusgraph_test + +import ( + "context" + "testing" + + mg "github.com/matthewmcneely/modusgraph" + "github.com/stretchr/testify/require" +) + +// lockLikeNode mirrors modusGraph-migrate's migrationLock: its Dgraph type +// name (declared via the DType tag, "DTypeMismatchType") differs from its Go +// struct name ("lockLikeNode"). +type lockLikeNode struct { + UID string `json:"uid,omitempty"` + DType []string `json:"dgraph.type,omitempty" dgraph:"DTypeMismatchType"` + Name string `json:"dtypeMismatchName,omitempty" dgraph:"predicate=dtype_mismatch_name index=exact"` +} + +// TestMutateValidation_ResolvesDTypeName guards the AutoSchema-disabled mutation +// path: it must resolve the type name from the DType tag (the same way schema +// generation and getNodeType do), not from the raw Go struct name. Before the +// fix, Insert rejected the row with "schema validation failed: database schema +// does not contain type lockLikeNode" even though the schema held the (correctly +// named) "type DTypeMismatchType". +func TestMutateValidation_ResolvesDTypeName(t *testing.T) { + client, err := mg.NewClient("file://" + GetTempDir(t)) // autoSchema disabled by default + require.NoError(t, err) + defer client.Close() + + ctx := context.Background() + // Register the type under its Dgraph name (derived from the DType tag). + require.NoError(t, client.UpdateSchema(ctx, &lockLikeNode{})) + + // Insert must pass validation now that the type name resolves via DType. + err = client.Insert(ctx, &lockLikeNode{DType: []string{"DTypeMismatchType"}, Name: "x"}) + require.NoError(t, err) +}