This is an automated email from the ASF dual-hosted git repository.

colegreer pushed a commit to branch goSerializerFixes
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 1116c6c9873306253a0f02e67e93332f54454bc2
Author: Cole Greer <[email protected]>
AuthorDate: Fri Mar 27 23:37:29 2026 -0700

    Fix misc GremlinLang and GraphBinary issues in Go
---
 gremlin-go/driver/graphBinaryDeserializer.go      |  26 ++++--
 gremlin-go/driver/graphBinaryDeserializer_test.go | 104 ++++++++++++++++++++++
 gremlin-go/driver/gremlinlang.go                  |   2 +-
 gremlin-go/driver/gremlinlang_test.go             |  12 +--
 gremlin-go/driver/traversal_test.go               |  12 +--
 5 files changed, 138 insertions(+), 18 deletions(-)

diff --git a/gremlin-go/driver/graphBinaryDeserializer.go 
b/gremlin-go/driver/graphBinaryDeserializer.go
index 8a61541599..dece9bcb3f 100644
--- a/gremlin-go/driver/graphBinaryDeserializer.go
+++ b/gremlin-go/driver/graphBinaryDeserializer.go
@@ -254,7 +254,7 @@ func (d *GraphBinaryDeserializer) readValue(dt dataType, 
flag byte) (interface{}
        case byteBuffer:
                return d.readByteBuffer()
        case tType, directionType, mergeType, gTypeType:
-               return d.readEnum()
+               return d.readEnum(dt)
        default:
                return nil, 
newError(err0408GetSerializerToReadUnknownTypeError, dt)
        }
@@ -479,6 +479,7 @@ func (d *GraphBinaryDeserializer) readVertexProperty() 
(*VertexProperty, error)
        }
        vp := &VertexProperty{
                Element: Element{Id: id, Label: label},
+               Key:     label,
                Value:   value,
        }
        vp.Properties = make([]interface{}, 0)
@@ -575,14 +576,29 @@ func (d *GraphBinaryDeserializer) readByteBuffer() 
(*ByteBuffer, error) {
        return &ByteBuffer{Data: data}, nil
 }
 
-func (d *GraphBinaryDeserializer) readEnum() (string, error) {
+func (d *GraphBinaryDeserializer) readEnum(dt dataType) (interface{}, error) {
        if _, err := d.readByte(); err != nil { // type code (string)
-               return "", err
+               return nil, err
        }
        if _, err := d.readByte(); err != nil { // null flag
-               return "", err
+               return nil, err
+       }
+       s, err := d.readString()
+       if err != nil {
+               return nil, err
+       }
+       switch dt {
+       case tType:
+               return t(s), nil
+       case directionType:
+               return direction(s), nil
+       case mergeType:
+               return merge(s), nil
+       case gTypeType:
+               return gType(s), nil
+       default:
+               return s, nil
        }
-       return d.readString()
 }
 
 // ReadStatus reads the response status after the EndOfStream marker.
diff --git a/gremlin-go/driver/graphBinaryDeserializer_test.go 
b/gremlin-go/driver/graphBinaryDeserializer_test.go
index f6490b425d..3b9fe9a52a 100644
--- a/gremlin-go/driver/graphBinaryDeserializer_test.go
+++ b/gremlin-go/driver/graphBinaryDeserializer_test.go
@@ -27,6 +27,7 @@ import (
        "time"
 
        "github.com/stretchr/testify/assert"
+       "golang.org/x/text/language"
 )
 
 // slowReader simulates a network stream that delivers data in chunks with 
delays.
@@ -369,6 +370,109 @@ func TestGraphBinaryDeserializerComplexTypes(t 
*testing.T) {
                assert.Equal(t, "person", v.Label)
        })
 
+       t.Run("round-trip VertexProperty preserves Key field", func(t 
*testing.T) {
+               original := &VertexProperty{
+                       Element: Element{Id: int32(1), Label: "name"},
+                       Key:     "name",
+                       Value:   "marko",
+               }
+
+               var buf bytes.Buffer
+               ser := newGraphBinarySerializer(newLogHandler(&defaultLogger{}, 
Error, language.English))
+               err := ser.ser.write(original, &buf)
+               assert.Nil(t, err)
+
+               d := NewGraphBinaryDeserializer(&buf)
+               val, err := d.ReadFullyQualified()
+               assert.Nil(t, err)
+
+               vp := val.(*VertexProperty)
+               assert.Equal(t, "marko", vp.Value)
+               assert.Equal(t, "name", vp.Key, "VertexProperty.Key should 
survive round-trip")
+       })
+
+       t.Run("round-trip map with T enum keys preserves types", func(t 
*testing.T) {
+               original := map[interface{}]interface{}{
+                       T.Id:    "1",
+                       T.Label: "person",
+                       "name":  "marko",
+               }
+
+               var buf bytes.Buffer
+               ser := newGraphBinarySerializer(newLogHandler(&defaultLogger{}, 
Error, language.English))
+               err := ser.ser.write(original, &buf)
+               assert.Nil(t, err)
+
+               d := NewGraphBinaryDeserializer(&buf)
+               val, err := d.ReadFullyQualified()
+               assert.Nil(t, err)
+
+               m := val.(map[interface{}]interface{})
+               assert.Equal(t, "1", m[T.Id], "T.Id key should survive 
round-trip")
+               assert.Equal(t, "person", m[T.Label], "T.Label key should 
survive round-trip")
+               assert.Equal(t, "marko", m["name"])
+       })
+
+       t.Run("round-trip map with Direction enum keys preserves types", func(t 
*testing.T) {
+               original := map[interface{}]interface{}{
+                       Direction.Out: "outVertex",
+                       Direction.In:  "inVertex",
+               }
+
+               var buf bytes.Buffer
+               ser := newGraphBinarySerializer(newLogHandler(&defaultLogger{}, 
Error, language.English))
+               err := ser.ser.write(original, &buf)
+               assert.Nil(t, err)
+
+               d := NewGraphBinaryDeserializer(&buf)
+               val, err := d.ReadFullyQualified()
+               assert.Nil(t, err)
+
+               m := val.(map[interface{}]interface{})
+               assert.Equal(t, "outVertex", m[Direction.Out], "Direction.Out 
key should survive round-trip")
+               assert.Equal(t, "inVertex", m[Direction.In], "Direction.In key 
should survive round-trip")
+       })
+
+       t.Run("round-trip map with Merge enum keys preserves types", func(t 
*testing.T) {
+               original := map[interface{}]interface{}{
+                       Merge.OnCreate: "created",
+                       Merge.OnMatch:  "matched",
+               }
+
+               var buf bytes.Buffer
+               ser := newGraphBinarySerializer(newLogHandler(&defaultLogger{}, 
Error, language.English))
+               err := ser.ser.write(original, &buf)
+               assert.Nil(t, err)
+
+               d := NewGraphBinaryDeserializer(&buf)
+               val, err := d.ReadFullyQualified()
+               assert.Nil(t, err)
+
+               m := val.(map[interface{}]interface{})
+               assert.Equal(t, "created", m[Merge.OnCreate], "Merge.OnCreate 
key should survive round-trip")
+               assert.Equal(t, "matched", m[Merge.OnMatch], "Merge.OnMatch key 
should survive round-trip")
+       })
+
+       t.Run("round-trip map with GType enum keys preserves types", func(t 
*testing.T) {
+               original := map[interface{}]interface{}{
+                       GType.Int:    "integer",
+                       GType.String: "string",
+               }
+
+               var buf bytes.Buffer
+               ser := newGraphBinarySerializer(newLogHandler(&defaultLogger{}, 
Error, language.English))
+               err := ser.ser.write(original, &buf)
+               assert.Nil(t, err)
+
+               d := NewGraphBinaryDeserializer(&buf)
+               val, err := d.ReadFullyQualified()
+               assert.Nil(t, err)
+
+               m := val.(map[interface{}]interface{})
+               assert.Equal(t, "integer", m[GType.Int], "GType.Int key should 
survive round-trip")
+               assert.Equal(t, "string", m[GType.String], "GType.String key 
should survive round-trip")
+       })
+
        t.Run("reads list of integers from chunked stream", func(t *testing.T) {
                // List type split across chunks
                chunk1 := []byte{
diff --git a/gremlin-go/driver/gremlinlang.go b/gremlin-go/driver/gremlinlang.go
index 92a66b28b6..baec7e6547 100644
--- a/gremlin-go/driver/gremlinlang.go
+++ b/gremlin-go/driver/gremlinlang.go
@@ -173,7 +173,7 @@ func (gl *GremlinLang) argAsString(arg interface{}) 
(string, error) {
        case *BigDecimal:
                return fmt.Sprintf("%vM", v.Value()), nil
        case time.Time:
-               return fmt.Sprintf("datetime(\"%v\")", v.Format(time.RFC3339)), 
nil
+               return fmt.Sprintf("datetime(\"%v\")", 
v.Format("2006-01-02T15:04:05.000Z07:00")), nil // equivalent to time.RFC3339 
but with ms precision instead of seconds
        case cardinality, column, direction, operator, order, pick, pop, 
barrier, scope, t, merge, gType:
                name := reflect.ValueOf(v).Type().Name()
                return fmt.Sprintf("%s.%s", strings.ToUpper(name[:1])+name[1:], 
v), nil
diff --git a/gremlin-go/driver/gremlinlang_test.go 
b/gremlin-go/driver/gremlinlang_test.go
index 30f66696b7..7160056f24 100644
--- a/gremlin-go/driver/gremlinlang_test.go
+++ b/gremlin-go/driver/gremlinlang_test.go
@@ -385,7 +385,7 @@ func Test_GremlinLang(t *testing.T) {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
                                return g.V().Has("date", P.Gt(time.Date(2021, 
1, 1, 9, 30, 0, 0, time.UTC)))
                        },
-                       equals: 
"g.V().has(\"date\",gt(datetime(\"2021-01-01T09:30:00Z\")))",
+                       equals: 
"g.V().has(\"date\",gt(datetime(\"2021-01-01T09:30:00.000Z\")))",
                },
                {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
@@ -481,31 +481,31 @@ func Test_GremlinLang(t *testing.T) {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
                                return g.V().Has("date", time.Date(2021, 2, 22, 
0, 0, 0, 0, time.UTC))
                        },
-                       equals: 
"g.V().has(\"date\",datetime(\"2021-02-22T00:00:00Z\"))",
+                       equals: 
"g.V().has(\"date\",datetime(\"2021-02-22T00:00:00.000Z\"))",
                },
                {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
                                return g.V().Has("date", 
P.Within(time.Date(2021, 2, 22, 0, 0, 0, 0, time.UTC), time.Date(2021, 1, 1, 0, 
0, 0, 0, time.UTC)))
                        },
-                       equals: 
"g.V().has(\"date\",within([datetime(\"2021-02-22T00:00:00Z\"),datetime(\"2021-01-01T00:00:00Z\")]))",
+                       equals: 
"g.V().has(\"date\",within([datetime(\"2021-02-22T00:00:00.000Z\"),datetime(\"2021-01-01T00:00:00.000Z\")]))",
                },
                {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
                                return g.V().Has("date", 
P.Between(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2021, 2, 22, 
0, 0, 0, 0, time.UTC)))
                        },
-                       equals: 
"g.V().has(\"date\",between(datetime(\"2021-01-01T00:00:00Z\"),datetime(\"2021-02-22T00:00:00Z\")))",
+                       equals: 
"g.V().has(\"date\",between(datetime(\"2021-01-01T00:00:00.000Z\"),datetime(\"2021-02-22T00:00:00.000Z\")))",
                },
                {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
                                return g.V().Has("date", 
P.Inside(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2021, 2, 22, 0, 
0, 0, 0, time.UTC)))
                        },
-                       equals: 
"g.V().has(\"date\",inside(datetime(\"2021-01-01T00:00:00Z\"),datetime(\"2021-02-22T00:00:00Z\")))",
+                       equals: 
"g.V().has(\"date\",inside(datetime(\"2021-01-01T00:00:00.000Z\"),datetime(\"2021-02-22T00:00:00.000Z\")))",
                },
                {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
                                return g.V().Has("date", P.Gt(time.Date(2021, 
1, 1, 9, 30, 0, 0, time.UTC)))
                        },
-                       equals: 
"g.V().has(\"date\",gt(datetime(\"2021-01-01T09:30:00Z\")))",
+                       equals: 
"g.V().has(\"date\",gt(datetime(\"2021-01-01T09:30:00.000Z\")))",
                },
                {
                        assert: func(g *GraphTraversalSource) *GraphTraversal {
diff --git a/gremlin-go/driver/traversal_test.go 
b/gremlin-go/driver/traversal_test.go
index 95eec7a5cb..e0795567b6 100644
--- a/gremlin-go/driver/traversal_test.go
+++ b/gremlin-go/driver/traversal_test.go
@@ -396,7 +396,7 @@ func TestTraversal(t *testing.T) {
 
                // Expect each result to contain a id. No additional items.
                for _, result := range results {
-                       key, ok := 
result.GetInterface().(map[interface{}]interface{})["id"]
+                       key, ok := 
result.GetInterface().(map[interface{}]interface{})[T.Id]
                        assert.True(t, ok)
                        assert.NotNil(t, key)
 
@@ -417,7 +417,7 @@ func TestTraversal(t *testing.T) {
 
                // Expect each result to contain a key. No additional items.
                for _, result := range results {
-                       key, ok := 
result.GetInterface().(map[interface{}]interface{})["key"]
+                       key, ok := 
result.GetInterface().(map[interface{}]interface{})[T.Key]
                        assert.True(t, ok)
                        assert.NotNil(t, key)
 
@@ -438,7 +438,7 @@ func TestTraversal(t *testing.T) {
 
                // Expect each result to contain a value. No additional items.
                for _, result := range results {
-                       key, ok := 
result.GetInterface().(map[interface{}]interface{})["value"]
+                       key, ok := 
result.GetInterface().(map[interface{}]interface{})[T.Value]
                        assert.True(t, ok)
                        assert.NotNil(t, key)
 
@@ -459,15 +459,15 @@ func TestTraversal(t *testing.T) {
 
                // Expect each result to contain an id, key, and value. No 
additional items.
                for _, result := range results {
-                       id, ok := 
result.GetInterface().(map[interface{}]interface{})["id"]
+                       id, ok := 
result.GetInterface().(map[interface{}]interface{})[T.Id]
                        assert.True(t, ok)
                        assert.NotNil(t, id)
 
-                       key, ok := 
result.GetInterface().(map[interface{}]interface{})["key"]
+                       key, ok := 
result.GetInterface().(map[interface{}]interface{})[T.Key]
                        assert.True(t, ok)
                        assert.NotNil(t, key)
 
-                       value, ok := 
result.GetInterface().(map[interface{}]interface{})["value"]
+                       value, ok := 
result.GetInterface().(map[interface{}]interface{})[T.Value]
                        assert.True(t, ok)
                        assert.NotNil(t, value)
 

Reply via email to