From 87ca74f028dfb760a90c862fb9aa4507ed1cbeb4 Mon Sep 17 00:00:00 2001 From: Jai Radhakrishnan <55522316+jairad26@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:58:53 -0800 Subject: [PATCH] move reflection logic to utils package --- .trunk/trunk.yaml | 2 +- api.go | 9 ++++++- api/utils/reflect.go | 34 ++++++++++++++++++++++++++ api/utils/utils.go | 13 ++++++++++ api_mutation_gen.go | 4 +-- api_mutation_helpers.go | 6 ++++- api_reflect.go | 54 ----------------------------------------- 7 files changed, 63 insertions(+), 59 deletions(-) delete mode 100644 api_reflect.go diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 85fae60..9442ef2 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -31,7 +31,7 @@ lint: - markdownlint@0.43.0 - osv-scanner@1.9.2 - prettier@3.4.2 - - renovate@39.88.0 + - renovate@39.90.2 - trufflehog@3.88.0 - yamllint@1.35.1 diff --git a/api.go b/api.go index beadf9f..ff10a00 100644 --- a/api.go +++ b/api.go @@ -67,10 +67,17 @@ func Upsert[T any](db *DB, object T, ns ...uint64) (uint64, T, bool, error) { return 0, object, false, err } - gid, cf, err := GetUniqueConstraint[T](object) + gid, cfKeyValue, err := utils.GetUniqueConstraint[T](object) if err != nil { return 0, object, false, err } + var cf *ConstrainedField + if cfKeyValue != nil { + cf = &ConstrainedField{ + Key: cfKeyValue.Key(), + Value: cfKeyValue.Value(), + } + } dms := make([]*dql.Mutation, 0) sch := &schema.ParsedSchema{} diff --git a/api/utils/reflect.go b/api/utils/reflect.go index a4a57e0..fb2cf04 100644 --- a/api/utils/reflect.go +++ b/api/utils/reflect.go @@ -208,3 +208,37 @@ func ConvertDynamicToTyped[T any](obj any, t reflect.Type) (uint64, T, error) { } return 0, result, fmt.Errorf("failed to convert type %T to %T", finalObject, obj) } + +func GetUniqueConstraint[T any](object T) (uint64, *keyValue, error) { + t := reflect.TypeOf(object) + fieldToJsonTags, jsonToDbTags, _, err := GetFieldTags(t) + if err != nil { + return 0, nil, err + } + jsonTagToValue := GetJsonTagToValues(object, fieldToJsonTags) + + for jsonName, value := range jsonTagToValue { + if jsonName == "gid" { + gid, ok := value.(uint64) + if !ok { + continue + } + if gid != 0 { + return gid, nil, nil + } + } + if jsonToDbTags[jsonName] != nil && IsValidUniqueIndex(jsonToDbTags[jsonName].Constraint) { + // check if value is zero or nil + if value == reflect.Zero(reflect.TypeOf(value)).Interface() || value == nil { + continue + } + return 0, &keyValue{key: jsonName, value: value}, nil + } + } + + return 0, nil, fmt.Errorf(NoUniqueConstr, t.Name()) +} + +func IsValidUniqueIndex(name string) bool { + return name == "unique" +} diff --git a/api/utils/utils.go b/api/utils/utils.go index ba726ed..03c2215 100644 --- a/api/utils/utils.go +++ b/api/utils/utils.go @@ -20,6 +20,19 @@ var ( NoUniqueConstr = "unique constraint not defined for any field on type %s" ) +type keyValue struct { + key string + value any +} + +func (kv *keyValue) Key() string { + return kv.key +} + +func (kv *keyValue) Value() any { + return kv.value +} + func GetPredicateName(typeName, fieldName string) string { return fmt.Sprint(typeName, ".", fieldName) } diff --git a/api_mutation_gen.go b/api_mutation_gen.go index 3bfdc6f..fb3b6c8 100644 --- a/api_mutation_gen.go +++ b/api_mutation_gen.go @@ -44,7 +44,7 @@ func generateSetDqlMutationsAndSchema[T any](ctx context.Context, n *Namespace, var nquad *api.NQuad if jsonToReverseEdgeTags[jsonName] != "" { - if err := mutations.HandleReverseEdge(jsonName, reflectValueType, n.id, sch, jsonToReverseEdgeTags); err != nil { + if err := mutations.HandleReverseEdge(jsonName, reflectValueType, n.ID(), sch, jsonToReverseEdgeTags); err != nil { return err } continue @@ -82,7 +82,7 @@ func generateSetDqlMutationsAndSchema[T any](ctx context.Context, n *Namespace, } sch.Types = append(sch.Types, &pb.TypeUpdate{ - TypeName: utils.AddNamespace(n.id, t.Name()), + TypeName: utils.AddNamespace(n.ID(), t.Name()), Fields: sch.Preds, }) diff --git a/api_mutation_helpers.go b/api_mutation_helpers.go index d4b0cf4..2016f04 100644 --- a/api_mutation_helpers.go +++ b/api_mutation_helpers.go @@ -38,10 +38,14 @@ func processPointerValue(ctx context.Context, value any, n *Namespace) (any, err } func getUidOrMutate[T any](ctx context.Context, db *DB, n *Namespace, object T) (uint64, error) { - gid, cf, err := GetUniqueConstraint[T](object) + gid, cfKeyValue, err := utils.GetUniqueConstraint[T](object) if err != nil { return 0, err } + var cf *ConstrainedField + if cfKeyValue != nil { + cf = &ConstrainedField{Key: cfKeyValue.Key(), Value: cfKeyValue.Value()} + } dms := make([]*dql.Mutation, 0) sch := &schema.ParsedSchema{} diff --git a/api_reflect.go b/api_reflect.go deleted file mode 100644 index 029a223..0000000 --- a/api_reflect.go +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2025 Hypermode Inc. - * Licensed under the terms of the Apache License, Version 2.0 - * See the LICENSE file that accompanied this code for further details. - * - * SPDX-FileCopyrightText: 2025 Hypermode Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -package modusdb - -import ( - "fmt" - "reflect" - - "github.com/hypermodeinc/modusdb/api/utils" -) - -func GetUniqueConstraint[T any](object T) (uint64, *ConstrainedField, error) { - t := reflect.TypeOf(object) - fieldToJsonTags, jsonToDbTags, _, err := utils.GetFieldTags(t) - if err != nil { - return 0, nil, err - } - jsonTagToValue := utils.GetJsonTagToValues(object, fieldToJsonTags) - - for jsonName, value := range jsonTagToValue { - if jsonName == "gid" { - gid, ok := value.(uint64) - if !ok { - continue - } - if gid != 0 { - return gid, nil, nil - } - } - if jsonToDbTags[jsonName] != nil && IsValidUniqueIndex(jsonToDbTags[jsonName].Constraint) { - // check if value is zero or nil - if value == reflect.Zero(reflect.TypeOf(value)).Interface() || value == nil { - continue - } - return 0, &ConstrainedField{ - Key: jsonName, - Value: value, - }, nil - } - } - - return 0, nil, fmt.Errorf(utils.NoUniqueConstr, t.Name()) -} - -func IsValidUniqueIndex(name string) bool { - return name == "unique" -}