[ 
https://issues.apache.org/jira/browse/TINKERPOP-2802?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17748673#comment-17748673
 ] 

ASF GitHub Bot commented on TINKERPOP-2802:
-------------------------------------------

j-white commented on code in PR #2174:
URL: https://github.com/apache/tinkerpop/pull/2174#discussion_r1277736470


##########
gremlin-go/driver/graphBinary.go:
##########
@@ -1282,6 +1284,78 @@ func metricsReader(data *[]byte, i *int) (interface{}, 
error) {
        return metrics, nil
 }
 
+type JanusgraphRelationIdentifier struct {

Review Comment:
   This will be moved outside of the driver, but including here for an example 
of what an implementation could look like.



##########
gremlin-go/driver/graphBinary.go:
##########
@@ -1282,6 +1284,78 @@ func metricsReader(data *[]byte, i *int) (interface{}, 
error) {
        return metrics, nil
 }
 
+type JanusgraphRelationIdentifier struct {
+       OutVertexIdLong   int64
+       OutVertexIdString string
+       TypeId            int64
+       RelationId        int64
+       InVertexIdLong    int64
+       InVertexIdString  string
+}
+
+func janusgraphRelationIdentifierReader(data *[]byte, i *int) (interface{}, 
error) {
+       const (
+               relationIdentifierType uint32 = 0x1001
+               longMarker             byte   = 0
+               stringMarker           byte   = 1
+       )
+
+       r := new(JanusgraphRelationIdentifier)
+
+       // expect type code
+       customDataTyp := readUint32Safe(data, i)
+       if customDataTyp != relationIdentifierType {
+               return nil, 
newError(err0408GetSerializerToReadUnknownTypeError, customDataTyp)
+       }
+
+       // value flag, expect this to be non-nullable
+       if readByteSafe(data, i) != valueFlagNone {
+               return nil, newError(err0405ReadValueInvalidNullInputError)
+       }
+
+       // outvertexid
+       if readByteSafe(data, i) == longMarker {
+               r.OutVertexIdLong = readLongSafe(data, i)
+       } else {
+               vertexId, err := readString(data, i)
+               if err != nil {
+                       return nil, err
+               }
+               r.OutVertexIdString = vertexId.(string)
+       }
+
+       r.TypeId = readLongSafe(data, i)
+       r.RelationId = readLongSafe(data, i)
+
+       // invertexid
+       if readByteSafe(data, i) == longMarker {
+               r.InVertexIdLong = readLongSafe(data, i)
+       } else {
+               vertexId, err := readString(data, i)
+               if err != nil {
+                       return nil, err
+               }
+               r.InVertexIdString = vertexId.(string)
+       }
+
+       return r, nil
+}
+
+// {name}{type specific payload}
+func customTypeReader(data *[]byte, i *int) (interface{}, error) {
+       // type name
+       *i = *i - 1
+       customTypeName, err := readString(data, i)
+       if err != nil {
+               return nil, err
+       }
+       deserializer, ok := customDeserializers[customTypeName.(string)]

Review Comment:
   For custom types, it looks like we write the name of the type, and then the 
remaining bytes are specific to the implementation. So it could make sense to 
key off the name, and let the custom reader handle the rest.
   
   Does this make sense?
   



##########
gremlin-go/driver/graphBinary.go:
##########
@@ -1282,6 +1284,78 @@ func metricsReader(data *[]byte, i *int) (interface{}, 
error) {
        return metrics, nil
 }
 
+type JanusgraphRelationIdentifier struct {
+       OutVertexIdLong   int64
+       OutVertexIdString string
+       TypeId            int64
+       RelationId        int64
+       InVertexIdLong    int64
+       InVertexIdString  string
+}
+
+func janusgraphRelationIdentifierReader(data *[]byte, i *int) (interface{}, 
error) {
+       const (
+               relationIdentifierType uint32 = 0x1001
+               longMarker             byte   = 0
+               stringMarker           byte   = 1
+       )
+
+       r := new(JanusgraphRelationIdentifier)
+
+       // expect type code
+       customDataTyp := readUint32Safe(data, i)
+       if customDataTyp != relationIdentifierType {
+               return nil, 
newError(err0408GetSerializerToReadUnknownTypeError, customDataTyp)
+       }
+
+       // value flag, expect this to be non-nullable
+       if readByteSafe(data, i) != valueFlagNone {
+               return nil, newError(err0405ReadValueInvalidNullInputError)
+       }
+
+       // outvertexid
+       if readByteSafe(data, i) == longMarker {
+               r.OutVertexIdLong = readLongSafe(data, i)
+       } else {
+               vertexId, err := readString(data, i)
+               if err != nil {
+                       return nil, err
+               }
+               r.OutVertexIdString = vertexId.(string)
+       }
+
+       r.TypeId = readLongSafe(data, i)
+       r.RelationId = readLongSafe(data, i)
+
+       // invertexid
+       if readByteSafe(data, i) == longMarker {
+               r.InVertexIdLong = readLongSafe(data, i)
+       } else {
+               vertexId, err := readString(data, i)
+               if err != nil {
+                       return nil, err
+               }
+               r.InVertexIdString = vertexId.(string)
+       }
+
+       return r, nil
+}
+
+// {name}{type specific payload}
+func customTypeReader(data *[]byte, i *int) (interface{}, error) {
+       // type name
+       *i = *i - 1

Review Comment:
   Need to backup the index by 1 to be read the 32-bit int with the size of the 
string



##########
gremlin-go/driver/graphBinary.go:
##########
@@ -224,11 +225,12 @@ func instructionWriter(instructions []instruction, buffer 
*bytes.Buffer, typeSer
 
 // Format: {steps_length}{step_0}…{step_n}{sources_length}{source_0}…{source_n}
 // Where:
-//             {steps_length} is an Int value describing the amount of steps.
-//             {step_i} is composed of 
{name}{values_length}{value_0}…{value_n}, where:
-//      {name} is a String. This is also known as the operator.
-//             {values_length} is an Int describing the amount values.
-//             {value_i} is a fully qualified typed value composed of 
{type_code}{type_info}{value_flag}{value} describing the step argument.
+//

Review Comment:
   unchanged, just go fmt



##########
gremlin-go/driver/graphBinary.go:
##########
@@ -1282,6 +1284,78 @@ func metricsReader(data *[]byte, i *int) (interface{}, 
error) {
        return metrics, nil
 }
 
+type JanusgraphRelationIdentifier struct {
+       OutVertexIdLong   int64
+       OutVertexIdString string
+       TypeId            int64
+       RelationId        int64
+       InVertexIdLong    int64
+       InVertexIdString  string
+}
+
+func janusgraphRelationIdentifierReader(data *[]byte, i *int) (interface{}, 
error) {
+       const (
+               relationIdentifierType uint32 = 0x1001
+               longMarker             byte   = 0
+               stringMarker           byte   = 1
+       )
+
+       r := new(JanusgraphRelationIdentifier)
+
+       // expect type code
+       customDataTyp := readUint32Safe(data, i)
+       if customDataTyp != relationIdentifierType {
+               return nil, 
newError(err0408GetSerializerToReadUnknownTypeError, customDataTyp)
+       }
+
+       // value flag, expect this to be non-nullable
+       if readByteSafe(data, i) != valueFlagNone {
+               return nil, newError(err0405ReadValueInvalidNullInputError)
+       }
+
+       // outvertexid
+       if readByteSafe(data, i) == longMarker {
+               r.OutVertexIdLong = readLongSafe(data, i)
+       } else {
+               vertexId, err := readString(data, i)
+               if err != nil {
+                       return nil, err
+               }
+               r.OutVertexIdString = vertexId.(string)
+       }
+
+       r.TypeId = readLongSafe(data, i)
+       r.RelationId = readLongSafe(data, i)
+
+       // invertexid
+       if readByteSafe(data, i) == longMarker {
+               r.InVertexIdLong = readLongSafe(data, i)
+       } else {
+               vertexId, err := readString(data, i)
+               if err != nil {
+                       return nil, err
+               }
+               r.InVertexIdString = vertexId.(string)
+       }
+
+       return r, nil
+}
+
+// {name}{type specific payload}
+func customTypeReader(data *[]byte, i *int) (interface{}, error) {
+       // type name
+       *i = *i - 1
+       customTypeName, err := readString(data, i)
+       if err != nil {
+               return nil, err
+       }
+       deserializer, ok := customDeserializers[customTypeName.(string)]
+       if !ok {
+               return nil, 
newError(err0408GetSerializerToReadUnknownTypeError, 0x00)

Review Comment:
   Introduce a new error code so we can pass the type name as a string? (this 
error code expects a number)



##########
gremlin-go/driver/serializer.go:
##########
@@ -320,5 +321,12 @@ func initDeserializers() {
                // Metrics
                metricsType:          metricsReader,
                traversalMetricsType: traversalMetricsReader,
+
+               // Customer
+               customType: customTypeReader,
+       }
+
+       customDeserializers = map[string]reader{

Review Comment:
   We could an option to provide this map during initialization. Would it make 
sense to add a property to the `DriverRemoteConnectionSettings` struct?





> Support Adding Custom Serializer for Gremlin Go
> -----------------------------------------------
>
>                 Key: TINKERPOP-2802
>                 URL: https://issues.apache.org/jira/browse/TINKERPOP-2802
>             Project: TinkerPop
>          Issue Type: Improvement
>          Components: go
>    Affects Versions: 3.6.2
>            Reporter: Yang Xia
>            Priority: Major
>
> To enable mechanisms to add custom serializers in the Go driver, for 
> compatibility with database specific types outside of TinkerPop, such as the 
> JanusGraph RelationIdentifier. 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to