diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 9442ef2..ef59a67 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -23,16 +23,16 @@ runtimes: # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) lint: enabled: - - actionlint@1.7.5 - - checkov@3.2.346 + - actionlint@1.7.6 + - checkov@3.2.350 - git-diff-check - gofmt@1.20.4 - - golangci-lint@1.62.2 + - golangci-lint@1.63.4 - markdownlint@0.43.0 - osv-scanner@1.9.2 - prettier@3.4.2 - - renovate@39.90.2 - - trufflehog@3.88.0 + - renovate@39.92.0 + - trufflehog@3.88.1 - yamllint@1.35.1 actions: diff --git a/CHANGELOG.md b/CHANGELOG.md index e92097c..0255986 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,10 @@ - feat: add readfrom json tag to support reverse edges [#49](https://github.com/hypermodeinc/modusDB/pull/49) -- chore: Refactoring package management #51 [#51](https://github.com/hypermodeinc/modusDB/pull/51) +- chore: Refactoring package management [#51](https://github.com/hypermodeinc/modusDB/pull/51) + +- fix: alter schema on reverse edge after querying schema + [#55](https://github.com/hypermodeinc/modusDB/pull/55) ## 2025-01-02 - Version 0.1.0 diff --git a/api/mutations/mutations.go b/api/mutations/mutations.go index 3a5e149..aea7657 100644 --- a/api/mutations/mutations.go +++ b/api/mutations/mutations.go @@ -22,8 +22,8 @@ import ( ) func HandleReverseEdge(jsonName string, value reflect.Type, nsId uint64, sch *schema.ParsedSchema, - jsonToReverseEdgeTags map[string]string) error { - if jsonToReverseEdgeTags[jsonName] == "" { + reverseEdgeStr string) error { + if reverseEdgeStr == "" { return nil } @@ -31,10 +31,9 @@ func HandleReverseEdge(jsonName string, value reflect.Type, nsId uint64, sch *sc return fmt.Errorf("reverse edge %s should be a slice of structs", jsonName) } - reverseEdge := jsonToReverseEdgeTags[jsonName] - typeName := strings.Split(reverseEdge, ".")[0] + typeName := strings.Split(reverseEdgeStr, ".")[0] u := &pb.SchemaUpdate{ - Predicate: apiutils.AddNamespace(nsId, reverseEdge), + Predicate: apiutils.AddNamespace(nsId, reverseEdgeStr), ValueType: pb.Posting_UID, Directive: pb.SchemaUpdate_REVERSE, } diff --git a/api/querygen/dql_query.go b/api/querygen/dql_query.go index f99234b..0a5a797 100644 --- a/api/querygen/dql_query.go +++ b/api/querygen/dql_query.go @@ -15,6 +15,19 @@ import ( "strings" ) +type SchemaField struct { + Name string `json:"name"` +} + +type SchemaType struct { + Name string `json:"name,omitempty"` + Fields []SchemaField `json:"fields,omitempty"` +} + +type SchemaResponse struct { + Types []SchemaType `json:"types,omitempty"` +} + type QueryFunc func() string const ( @@ -56,6 +69,10 @@ const ( } ` + SchemaQuery = ` + schema{} + ` + FuncUid = `uid(%d)` FuncEq = `eq(%s, %s)` FuncSimilarTo = `similar_to(%s, %d, "[%s]")` diff --git a/api_mutation_gen.go b/api_mutation_gen.go index 6e8426c..d8533fc 100644 --- a/api_mutation_gen.go +++ b/api_mutation_gen.go @@ -13,6 +13,7 @@ import ( "context" "fmt" "reflect" + "strings" "github.com/dgraph-io/dgo/v240/protos/api" "github.com/dgraph-io/dgraph/v24/dql" @@ -46,10 +47,34 @@ func generateSetDqlMutationsAndSchema[T any](ctx context.Context, n *Namespace, var nquad *api.NQuad if tagMaps.JsonToReverseEdge[jsonName] != "" { - if err := mutations.HandleReverseEdge(jsonName, reflectValueType, n.ID(), sch, - tagMaps.JsonToReverseEdge); err != nil { + reverseEdgeStr := tagMaps.JsonToReverseEdge[jsonName] + typeName := strings.Split(reverseEdgeStr, ".")[0] + currSchema, err := getSchema(ctx, n) + if err != nil { return err } + + typeFound := false + predicateFound := false + for _, t := range currSchema.Types { + if t.Name == typeName { + typeFound = true + for _, f := range t.Fields { + if f.Name == reverseEdgeStr { + predicateFound = true + break + } + } + break + } + } + + if !(typeFound && predicateFound) { + if err := mutations.HandleReverseEdge(jsonName, reflectValueType, n.ID(), sch, + reverseEdgeStr); err != nil { + return err + } + } continue } if jsonName == "gid" { diff --git a/api_query_execution.go b/api_query_execution.go index 4129870..d6e0323 100644 --- a/api_query_execution.go +++ b/api_query_execution.go @@ -199,3 +199,16 @@ func getExistingObject[T any](ctx context.Context, n *Namespace, gid uint64, cf } return gid, nil } + +func getSchema(ctx context.Context, n *Namespace) (*querygen.SchemaResponse, error) { + resp, err := n.queryWithLock(ctx, querygen.SchemaQuery) + if err != nil { + return nil, err + } + + var schema querygen.SchemaResponse + if err := json.Unmarshal(resp.Json, &schema); err != nil { + return nil, err + } + return &schema, nil +} diff --git a/api_test.go b/api_test.go index 3326d86..0891069 100644 --- a/api_test.go +++ b/api_test.go @@ -110,23 +110,36 @@ func TestCreateApi(t *testing.T) { string(resp.GetJson())) // TODO schema{} should work - schemaQuery := `schema(pred: [User.name, User.age, User.clerk_id]) - { - type - index - tokenizer - }` + schemaQuery := `schema{}` resp, err = db1.Query(ctx, schemaQuery) require.NoError(t, err) require.JSONEq(t, - `{"schema": - [ - {"predicate":"User.age","type":"int"}, - {"predicate":"User.clerk_id","type":"string","index":true,"tokenizer":["exact"]}, - {"predicate":"User.name","type":"string"} - ] - }`, + `{ + "types": [ + { + "name": "User", + "fields": [ + {"name": "User.name"}, + {"name": "User.age"}, + {"name": "User.clerk_id"} + ] + }, + { + "name": "dgraph.graphql", + "fields": [ + {"name": "dgraph.graphql.schema"}, + {"name": "dgraph.graphql.xid"} + ] + }, + { + "name": "dgraph.graphql.persisted_query", + "fields": [ + {"name": "dgraph.graphql.p_query"} + ] + } + ] + }`, string(resp.GetJson())) }