This is an automated email from the ASF dual-hosted git repository. xiazcy pushed a commit to branch gremlin-go-http in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit b095321a48446fd7043ebcb58c1f30675fc4c944 Author: Yang Xia <[email protected]> AuthorDate: Mon Jan 27 18:28:00 2025 -0800 Add GremlinLang to Go driver (#2965) * Added GremlinLang to go driver to replace Bytecode. Clean up and updates will be needed when connection is set up. --- gremlin-go/driver/anonymousTraversal.go | 2 +- gremlin-go/driver/client.go | 10 + gremlin-go/driver/connection_test.go | 2 +- gremlin-go/driver/driverRemoteConnection.go | 9 + gremlin-go/driver/error_codes.go | 7 +- gremlin-go/driver/graphTraversal.go | 285 +++++----- gremlin-go/driver/graphTraversalSource.go | 67 +-- gremlin-go/driver/graphTraversalSource_test.go | 1 + gremlin-go/driver/gremlinlang.go | 513 ++++++++++++++++++ gremlin-go/driver/gremlinlang_test.go | 717 +++++++++++++++++++++++++ gremlin-go/driver/strategies.go | 2 +- gremlin-go/driver/traversal.go | 23 +- gremlin-go/driver/traversal_test.go | 4 +- gremlin-go/examples/go.mod | 2 +- gremlin-go/go.mod | 2 +- 15 files changed, 1446 insertions(+), 200 deletions(-) diff --git a/gremlin-go/driver/anonymousTraversal.go b/gremlin-go/driver/anonymousTraversal.go index 00892d75da..c65bf95d63 100644 --- a/gremlin-go/driver/anonymousTraversal.go +++ b/gremlin-go/driver/anonymousTraversal.go @@ -329,7 +329,7 @@ type anonymousTraversal struct { var T__ AnonymousTraversal = &anonymousTraversal{ func() *GraphTraversal { - return NewGraphTraversal(nil, NewBytecode(nil), nil) + return NewGraphTraversal(nil, NewGremlinLang(nil), nil) }, } diff --git a/gremlin-go/driver/client.go b/gremlin-go/driver/client.go index 5c9dedaa4e..e30f7daae5 100644 --- a/gremlin-go/driver/client.go +++ b/gremlin-go/driver/client.go @@ -170,6 +170,16 @@ func (client *Client) Submit(traversalString string, bindings ...map[string]inte return client.SubmitWithOptions(traversalString, requestOptionsBuilder.Create()) } +// submitGremlinLang submits GremlinLang to the server to execute and returns a ResultSet. +// TODO test and update when connection is set up +func (client *Client) submitGremlinLang(gremlinLang *GremlinLang) (ResultSet, error) { + client.logHandler.logf(Debug, submitStartedString, *gremlinLang) + // TODO placeholder + requestOptionsBuilder := new(RequestOptionsBuilder) + request := makeStringRequest(gremlinLang.GetGremlin(), client.traversalSource, client.session, requestOptionsBuilder.Create()) + return client.connections.write(&request) +} + // submitBytecode submits Bytecode to the server to execute and returns a ResultSet. func (client *Client) submitBytecode(bytecode *Bytecode) (ResultSet, error) { client.logHandler.logf(Debug, submitStartedBytecode, *bytecode) diff --git a/gremlin-go/driver/connection_test.go b/gremlin-go/driver/connection_test.go index e8b2383aa0..6bcb2e75dd 100644 --- a/gremlin-go/driver/connection_test.go +++ b/gremlin-go/driver/connection_test.go @@ -606,7 +606,7 @@ func TestConnection(t *testing.T) { assert.True(t, ok) assert.NotNil(t, result) - g := cloneGraphTraversalSource(&Graph{}, NewBytecode(nil), nil) + g := cloneGraphTraversalSource(&Graph{}, NewBytecode(nil), NewGremlinLang(nil), nil) b := g.V().Count().Bytecode resultSet, err = client.submitBytecode(b) assert.Nil(t, err) diff --git a/gremlin-go/driver/driverRemoteConnection.go b/gremlin-go/driver/driverRemoteConnection.go index 8a39c7bcba..a8dce4985c 100644 --- a/gremlin-go/driver/driverRemoteConnection.go +++ b/gremlin-go/driver/driverRemoteConnection.go @@ -178,6 +178,15 @@ func (driver *DriverRemoteConnection) Submit(traversalString string) (ResultSet, return driver.SubmitWithOptions(traversalString, *new(RequestOptions)) } +// submitGremlinLang sends a GremlinLang traversal to the server. +// TODO test and update when connection is set up +func (driver *DriverRemoteConnection) submitGremlinLang(gremlinLang *GremlinLang) (ResultSet, error) { + if driver.isClosed { + return nil, newError(err0203SubmitGremlinLangToClosedConnectionError) + } + return driver.client.submitGremlinLang(gremlinLang) +} + // submitBytecode sends a Bytecode traversal to the server. func (driver *DriverRemoteConnection) submitBytecode(bytecode *Bytecode) (ResultSet, error) { if driver.isClosed { diff --git a/gremlin-go/driver/error_codes.go b/gremlin-go/driver/error_codes.go index 7e1a62ae2b..875b10c1d9 100644 --- a/gremlin-go/driver/error_codes.go +++ b/gremlin-go/driver/error_codes.go @@ -42,9 +42,10 @@ const ( err0105ConnectionPoolFullButNoneValid errorCode = "E0105_CONNECTIONPOOL_FULL_NONE_VALID" // driverRemoteConnection.go errors - err0201CreateSessionMultipleIdsError errorCode = "E0201_DRIVER_REMOTE_CONNECTION_CREATESESSION_MULTIPLE_UUIDS_ERROR" - err0202CreateSessionFromSessionError errorCode = "E0202_DRIVER_REMOTE_CONNECTION_CREATESESSION_SESSION_FROM_SESSION_ERROR" - err0203SubmitBytecodeToClosedConnectionError errorCode = "E0203_DRIVER_REMOTE_CONNECTION_SUBMITBYTECODE_TO_CLOSED_CONNECTION_ERROR" + err0201CreateSessionMultipleIdsError errorCode = "E0201_DRIVER_REMOTE_CONNECTION_CREATESESSION_MULTIPLE_UUIDS_ERROR" + err0202CreateSessionFromSessionError errorCode = "E0202_DRIVER_REMOTE_CONNECTION_CREATESESSION_SESSION_FROM_SESSION_ERROR" + err0203SubmitGremlinLangToClosedConnectionError errorCode = "E0203_DRIVER_REMOTE_CONNECTION_SUBMITGREMLINLANG_TO_CLOSED_CONNECTION_ERROR" + err0203SubmitBytecodeToClosedConnectionError errorCode = "E0203_DRIVER_REMOTE_CONNECTION_SUBMITBYTECODE_TO_CLOSED_CONNECTION_ERROR" // graph.go errors err0301GetPathObjectInvalidPathUnequalLengthsError errorCode = "E0301_GRAPH_GETPATHOBJECT_UNEQUAL_LABELS_OBJECTS_LENGTH_ERROR" diff --git a/gremlin-go/driver/graphTraversal.go b/gremlin-go/driver/graphTraversal.go index 657e5ea988..cf3ca8eb18 100644 --- a/gremlin-go/driver/graphTraversal.go +++ b/gremlin-go/driver/graphTraversal.go @@ -36,12 +36,15 @@ type GraphTraversal struct { // NewGraphTraversal make a new GraphTraversal. // why is this taking a non exported field as an exported function - remove or replace? -func NewGraphTraversal(graph *Graph, bytecode *Bytecode, remote *DriverRemoteConnection) *GraphTraversal { +func NewGraphTraversal(graph *Graph, gremlinLang *GremlinLang, remote *DriverRemoteConnection) *GraphTraversal { + if gremlinLang == nil { + gremlinLang = NewGremlinLang(nil) + } gt := &GraphTraversal{ Traversal: &Traversal{ - graph: graph, - Bytecode: bytecode, - remote: remote, + graph: graph, + GremlinLang: gremlinLang, + remote: remote, }, } return gt @@ -49,823 +52,823 @@ func NewGraphTraversal(graph *Graph, bytecode *Bytecode, remote *DriverRemoteCon // Clone make a copy of a traversal that is reset for iteration. func (g *GraphTraversal) Clone() *GraphTraversal { - return NewGraphTraversal(g.graph, NewBytecode(g.Bytecode), g.remote) + return NewGraphTraversal(g.graph, NewGremlinLang(g.GremlinLang), g.remote) } // V adds the v step to the GraphTraversal. func (g *GraphTraversal) V(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("V", args...) + g.GremlinLang.AddStep("V", args...) return g } // E adds the e step to the GraphTraversal. func (g *GraphTraversal) E(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("E", args...) + g.GremlinLang.AddStep("E", args...) return g } // AddE adds the addE step to the GraphTraversal. func (g *GraphTraversal) AddE(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("addE", args...) + g.GremlinLang.AddStep("addE", args...) return g } // AddV adds the addV step to the GraphTraversal. func (g *GraphTraversal) AddV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("addV", args...) + g.GremlinLang.AddStep("addV", args...) return g } // Aggregate adds the aggregate step to the GraphTraversal. func (g *GraphTraversal) Aggregate(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("aggregate", args...) + g.GremlinLang.AddStep("aggregate", args...) return g } // All adds the all step to the GraphTraversal. func (g *GraphTraversal) All(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("all", args...) + g.GremlinLang.AddStep("all", args...) return g } // And adds the and step to the GraphTraversal. func (g *GraphTraversal) And(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("and", args...) + g.GremlinLang.AddStep("and", args...) return g } // Any adds the any step to the GraphTraversal. func (g *GraphTraversal) Any(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("any", args...) + g.GremlinLang.AddStep("any", args...) return g } // As adds the as step to the GraphTraversal. func (g *GraphTraversal) As(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("as", args...) + g.GremlinLang.AddStep("as", args...) return g } // AsDate adds the asDate step to the GraphTraversal. func (g *GraphTraversal) AsDate(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("asDate", args...) + g.GremlinLang.AddStep("asDate", args...) return g } // AsString adds the asString step to the GraphTraversal. func (g *GraphTraversal) AsString(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("asString", args...) + g.GremlinLang.AddStep("asString", args...) return g } // Barrier adds the barrier step to the GraphTraversal. func (g *GraphTraversal) Barrier(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("barrier", int32Args(args)...) + g.GremlinLang.AddStep("barrier", int32Args(args)...) return g } // Both adds the both step to the GraphTraversal. func (g *GraphTraversal) Both(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("both", args...) + g.GremlinLang.AddStep("both", args...) return g } // BothE adds the bothE step to the GraphTraversal. func (g *GraphTraversal) BothE(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("bothE", args...) + g.GremlinLang.AddStep("bothE", args...) return g } // BothV adds the bothV step to the GraphTraversal. func (g *GraphTraversal) BothV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("bothV", args...) + g.GremlinLang.AddStep("bothV", args...) return g } // Branch adds the branch step to the GraphTraversal. func (g *GraphTraversal) Branch(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("branch", args...) + g.GremlinLang.AddStep("branch", args...) return g } // By adds the by step to the GraphTraversal. func (g *GraphTraversal) By(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("by", args...) + g.GremlinLang.AddStep("by", args...) return g } // Call adds the call step to the GraphTraversal. func (g *GraphTraversal) Call(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("call", args...) + g.GremlinLang.AddStep("call", args...) return g } // Cap adds the cap step to the GraphTraversal. func (g *GraphTraversal) Cap(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("cap", args...) + g.GremlinLang.AddStep("cap", args...) return g } // Choose adds the choose step to the GraphTraversal. func (g *GraphTraversal) Choose(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("choose", args...) + g.GremlinLang.AddStep("choose", args...) return g } // Coalesce adds the coalesce step to the GraphTraversal. func (g *GraphTraversal) Coalesce(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("coalesce", args...) + g.GremlinLang.AddStep("coalesce", args...) return g } // Coin adds the coint step to the GraphTraversal. func (g *GraphTraversal) Coin(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("coin", args...) + g.GremlinLang.AddStep("coin", args...) return g } // Combine adds the combine step to the GraphTraversal. func (g *GraphTraversal) Combine(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("combine", args...) + g.GremlinLang.AddStep("combine", args...) return g } // Concat adds the concat step to the GraphTraversal. func (g *GraphTraversal) Concat(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("concat", args...) + g.GremlinLang.AddStep("concat", args...) return g } // Conjoin adds the conjoin step to the GraphTraversal. func (g *GraphTraversal) Conjoin(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("conjoin", args...) + g.GremlinLang.AddStep("conjoin", args...) return g } // ConnectedComponent adds the connectedComponent step to the GraphTraversal. func (g *GraphTraversal) ConnectedComponent(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("connectedComponent", args...) + g.GremlinLang.AddStep("connectedComponent", args...) return g } // Constant adds the constant step to the GraphTraversal. func (g *GraphTraversal) Constant(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("constant", int32Args(args)...) + g.GremlinLang.AddStep("constant", int32Args(args)...) return g } // Count adds the count step to the GraphTraversal. func (g *GraphTraversal) Count(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("count", args...) + g.GremlinLang.AddStep("count", args...) return g } // CyclicPath adds the cyclicPath step to the GraphTraversal. func (g *GraphTraversal) CyclicPath(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("cyclicPath", args...) + g.GremlinLang.AddStep("cyclicPath", args...) return g } // DateAdd adds the dateAdd step to the GraphTraversal. func (g *GraphTraversal) DateAdd(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("dateAdd", int32Args(args)...) + g.GremlinLang.AddStep("dateAdd", int32Args(args)...) return g } // DateDiff adds the dateDiff step to the GraphTraversal. func (g *GraphTraversal) DateDiff(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("dateDiff", args...) + g.GremlinLang.AddStep("dateDiff", args...) return g } // Dedup adds the dedup step to the GraphTraversal. func (g *GraphTraversal) Dedup(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("dedup", args...) + g.GremlinLang.AddStep("dedup", args...) return g } // Difference adds the difference step to the GraphTraversal. func (g *GraphTraversal) Difference(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("difference", args...) + g.GremlinLang.AddStep("difference", args...) return g } // Discard adds the discard step to the GraphTraversal. func (g *GraphTraversal) Discard(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("discard", args...) + g.GremlinLang.AddStep("discard", args...) return g } // Disjunct adds the disjunct step to the GraphTraversal. func (g *GraphTraversal) Disjunct(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("disjunct", args...) + g.GremlinLang.AddStep("disjunct", args...) return g } // Drop adds the drop step to the GraphTraversal. func (g *GraphTraversal) Drop(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("drop", args...) + g.GremlinLang.AddStep("drop", args...) return g } // Element adds the element step to the GraphTraversal. func (g *GraphTraversal) Element(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("element", args...) + g.GremlinLang.AddStep("element", args...) return g } // ElementMap adds the elementMap step to the GraphTraversal. func (g *GraphTraversal) ElementMap(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("elementMap", args...) + g.GremlinLang.AddStep("elementMap", args...) return g } // Emit adds the emit step to the GraphTraversal. func (g *GraphTraversal) Emit(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("emit", args...) + g.GremlinLang.AddStep("emit", args...) return g } // Fail adds the fail step to the GraphTraversal. func (g *GraphTraversal) Fail(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("fail", args...) + g.GremlinLang.AddStep("fail", args...) return g } // Filter adds the filter step to the GraphTraversal. func (g *GraphTraversal) Filter(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("filter", args...) + g.GremlinLang.AddStep("filter", args...) return g } // FlatMap adds the flatMap step to the GraphTraversal. func (g *GraphTraversal) FlatMap(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("flatMap", args...) + g.GremlinLang.AddStep("flatMap", args...) return g } // Fold adds the fold step to the GraphTraversal. func (g *GraphTraversal) Fold(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("fold", args...) + g.GremlinLang.AddStep("fold", args...) return g } // Format adds the format step to the GraphTraversal. func (g *GraphTraversal) Format(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("format", args...) + g.GremlinLang.AddStep("format", args...) return g } // From adds the from step to the GraphTraversal. func (g *GraphTraversal) From(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("from", args...) + g.GremlinLang.AddStep("from", args...) return g } // Group adds the group step to the GraphTraversal. func (g *GraphTraversal) Group(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("group", args...) + g.GremlinLang.AddStep("group", args...) return g } // GroupCount adds the groupCount step to the GraphTraversal. func (g *GraphTraversal) GroupCount(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("groupCount", args...) + g.GremlinLang.AddStep("groupCount", args...) return g } // Has adds the has step to the GraphTraversal. func (g *GraphTraversal) Has(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("has", args...) + g.GremlinLang.AddStep("has", args...) return g } // HasId adds the hasId step to the GraphTraversal. func (g *GraphTraversal) HasId(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("hasId", args...) + g.GremlinLang.AddStep("hasId", args...) return g } // HasKey adds the hasKey step to the GraphTraversal. func (g *GraphTraversal) HasKey(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("hasKey", args...) + g.GremlinLang.AddStep("hasKey", args...) return g } // HasLabel adds the hasLabel step to the GraphTraversal. func (g *GraphTraversal) HasLabel(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("hasLabel", args...) + g.GremlinLang.AddStep("hasLabel", args...) return g } // HasNot adds the hasNot step to the GraphTraversal. func (g *GraphTraversal) HasNot(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("hasNot", args...) + g.GremlinLang.AddStep("hasNot", args...) return g } // HasValue adds the hasValue step to the GraphTraversal. func (g *GraphTraversal) HasValue(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("hasValue", args...) + g.GremlinLang.AddStep("hasValue", args...) return g } // Id adds the id step to the GraphTraversal. func (g *GraphTraversal) Id(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("id", args...) + g.GremlinLang.AddStep("id", args...) return g } // Identity adds the identity step to the GraphTraversal. func (g *GraphTraversal) Identity(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("identity", args...) + g.GremlinLang.AddStep("identity", args...) return g } // InE adds the inE step to the GraphTraversal. func (g *GraphTraversal) InE(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("inE", args...) + g.GremlinLang.AddStep("inE", args...) return g } // InV adds the inV step to the GraphTraversal. func (g *GraphTraversal) InV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("inV", args...) + g.GremlinLang.AddStep("inV", args...) return g } // In adds the in step to the GraphTraversal. func (g *GraphTraversal) In(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("in", args...) + g.GremlinLang.AddStep("in", args...) return g } // Index adds the index step to the GraphTraversal. func (g *GraphTraversal) Index(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("index", args...) + g.GremlinLang.AddStep("index", args...) return g } // Inject adds the inject step to the GraphTraversal. func (g *GraphTraversal) Inject(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("inject", int32Args(args)...) + g.GremlinLang.AddStep("inject", int32Args(args)...) return g } // Intersect adds the intersect step to the GraphTraversal. func (g *GraphTraversal) Intersect(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("intersect", args...) + g.GremlinLang.AddStep("intersect", args...) return g } // Is adds the is step to the GraphTraversal. func (g *GraphTraversal) Is(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("is", args...) + g.GremlinLang.AddStep("is", args...) return g } // Key adds the key step to the GraphTraversal. func (g *GraphTraversal) Key(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("key", args...) + g.GremlinLang.AddStep("key", args...) return g } // Label adds the label step to the GraphTraversal. func (g *GraphTraversal) Label(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("label", args...) + g.GremlinLang.AddStep("label", args...) return g } // Length adds the length step to the GraphTraversal. func (g *GraphTraversal) Length(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("length", args...) + g.GremlinLang.AddStep("length", args...) return g } // Limit adds the limit step to the GraphTraversal. func (g *GraphTraversal) Limit(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("limit", args...) + g.GremlinLang.AddStep("limit", args...) return g } // Local adds the local step to the GraphTraversal. func (g *GraphTraversal) Local(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("local", args...) + g.GremlinLang.AddStep("local", args...) return g } // Loops adds the loops step to the GraphTraversal. func (g *GraphTraversal) Loops(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("loops", args...) + g.GremlinLang.AddStep("loops", args...) return g } // LTrim adds the lTrim step to the GraphTraversal. func (g *GraphTraversal) LTrim(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("lTrim", args...) + g.GremlinLang.AddStep("lTrim", args...) return g } // Map adds the map step to the GraphTraversal. func (g *GraphTraversal) Map(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("map", args...) + g.GremlinLang.AddStep("map", args...) return g } // Match adds the match step to the GraphTraversal. func (g *GraphTraversal) Match(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("match", args...) + g.GremlinLang.AddStep("match", args...) return g } // Math adds the math step to the GraphTraversal. func (g *GraphTraversal) Math(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("math", args...) + g.GremlinLang.AddStep("math", args...) return g } // Max adds the max step to the GraphTraversal. func (g *GraphTraversal) Max(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("max", args...) + g.GremlinLang.AddStep("max", args...) return g } // Mean adds the mean step to the GraphTraversal. func (g *GraphTraversal) Mean(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("mean", args...) + g.GremlinLang.AddStep("mean", args...) return g } // Merge adds the merge step to the GraphTraversal. func (g *GraphTraversal) Merge(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("merge", args...) + g.GremlinLang.AddStep("merge", args...) return g } // MergeE adds the mergeE step to the GraphTraversal. func (g *GraphTraversal) MergeE(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("mergeE", args...) + g.GremlinLang.AddStep("mergeE", args...) return g } // MergeV adds the mergeE step to the GraphTraversal. func (g *GraphTraversal) MergeV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("mergeV", args...) + g.GremlinLang.AddStep("mergeV", args...) return g } // Min adds the min step to the GraphTraversal. func (g *GraphTraversal) Min(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("min", args...) + g.GremlinLang.AddStep("min", args...) return g } // None adds the none step to the GraphTraversal. func (g *GraphTraversal) None(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("none", args...) + g.GremlinLang.AddStep("none", args...) return g } // Not adds the not step to the GraphTraversal. func (g *GraphTraversal) Not(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("not", args...) + g.GremlinLang.AddStep("not", args...) return g } // Option adds the option step to the GraphTraversal. func (g *GraphTraversal) Option(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("option", args...) + g.GremlinLang.AddStep("option", args...) return g } // Optional adds the optional step to the GraphTraversal. func (g *GraphTraversal) Optional(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("optional", args...) + g.GremlinLang.AddStep("optional", args...) return g } // Or adds the or step to the GraphTraversal. func (g *GraphTraversal) Or(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("or", args...) + g.GremlinLang.AddStep("or", args...) return g } // Order adds the order step to the GraphTraversal. func (g *GraphTraversal) Order(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("order", args...) + g.GremlinLang.AddStep("order", args...) return g } // OtherV adds the otherV step to the GraphTraversal. func (g *GraphTraversal) OtherV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("otherV", args...) + g.GremlinLang.AddStep("otherV", args...) return g } // Out adds the out step to the GraphTraversal. func (g *GraphTraversal) Out(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("out", args...) + g.GremlinLang.AddStep("out", args...) return g } // OutE adds the outE step to the GraphTraversal. func (g *GraphTraversal) OutE(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("outE", args...) + g.GremlinLang.AddStep("outE", args...) return g } // OutV adds the outV step to the GraphTraversal. func (g *GraphTraversal) OutV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("outV", args...) + g.GremlinLang.AddStep("outV", args...) return g } // PageRank adds the pageRank step to the GraphTraversal. func (g *GraphTraversal) PageRank(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("pageRank", args...) + g.GremlinLang.AddStep("pageRank", args...) return g } // Path adds the path step to the GraphTraversal. func (g *GraphTraversal) Path(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("path", args...) + g.GremlinLang.AddStep("path", args...) return g } // PeerPressure adds the peerPressure step to the GraphTraversal. func (g *GraphTraversal) PeerPressure(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("peerPressure", args...) + g.GremlinLang.AddStep("peerPressure", args...) return g } // Product adds the product step to the GraphTraversal. func (g *GraphTraversal) Product(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("product", args...) + g.GremlinLang.AddStep("product", args...) return g } // Profile adds the profile step to the GraphTraversal. func (g *GraphTraversal) Profile(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("profile", args...) + g.GremlinLang.AddStep("profile", args...) return g } // Program adds the program step to the GraphTraversal. func (g *GraphTraversal) Program(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("program", args...) + g.GremlinLang.AddStep("program", args...) return g } // Project adds the project step to the GraphTraversal. func (g *GraphTraversal) Project(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("project", args...) + g.GremlinLang.AddStep("project", args...) return g } // Properties adds the properties step to the GraphTraversal. func (g *GraphTraversal) Properties(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("properties", args...) + g.GremlinLang.AddStep("properties", args...) return g } // Property adds the property step to the GraphTraversal. func (g *GraphTraversal) Property(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("property", args...) + g.GremlinLang.AddStep("property", args...) return g } // PropertyMap adds the propertyMap step to the GraphTraversal. func (g *GraphTraversal) PropertyMap(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("propertyMap", args...) + g.GremlinLang.AddStep("propertyMap", args...) return g } // Range adds the range step to the GraphTraversal. func (g *GraphTraversal) Range(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("range", args...) + g.GremlinLang.AddStep("range", args...) return g } // Read adds the read step to the GraphTraversal. func (g *GraphTraversal) Read(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("read", args...) + g.GremlinLang.AddStep("read", args...) return g } // Repeat adds the repeat step to the GraphTraversal. func (g *GraphTraversal) Repeat(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("repeat", args...) + g.GremlinLang.AddStep("repeat", args...) return g } // Replace adds the replace step to the GraphTraversal. func (g *GraphTraversal) Replace(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("replace", args...) + g.GremlinLang.AddStep("replace", args...) return g } // Reverse adds the reverse step to the GraphTraversal. func (g *GraphTraversal) Reverse(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("reverse", args...) + g.GremlinLang.AddStep("reverse", args...) return g } // RTrim adds the repeat step to the GraphTraversal. func (g *GraphTraversal) RTrim(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("rTrim", args...) + g.GremlinLang.AddStep("rTrim", args...) return g } // Sack adds the sack step to the GraphTraversal. func (g *GraphTraversal) Sack(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("sack", args...) + g.GremlinLang.AddStep("sack", args...) return g } // Sample adds the sample step to the GraphTraversal. func (g *GraphTraversal) Sample(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("sample", int32Args(args)...) + g.GremlinLang.AddStep("sample", int32Args(args)...) return g } // Select adds the select step to the GraphTraversal. func (g *GraphTraversal) Select(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("select", args...) + g.GremlinLang.AddStep("select", args...) return g } // ShortestPath adds the shortestPath step to the GraphTraversal. func (g *GraphTraversal) ShortestPath(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("shortestPath", args...) + g.GremlinLang.AddStep("shortestPath", args...) return g } // SideEffect adds the sideEffect step to the GraphTraversal. func (g *GraphTraversal) SideEffect(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("sideEffect", args...) + g.GremlinLang.AddStep("sideEffect", args...) return g } // SimplePath adds the simplePath step to the GraphTraversal. func (g *GraphTraversal) SimplePath(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("simplePath", args...) + g.GremlinLang.AddStep("simplePath", args...) return g } // Skip adds the skip step to the GraphTraversal. func (g *GraphTraversal) Skip(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("skip", args...) + g.GremlinLang.AddStep("skip", args...) return g } // Split adds the split step to the GraphTraversal. func (g *GraphTraversal) Split(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("split", args...) + g.GremlinLang.AddStep("split", args...) return g } // Store adds the store step to the GraphTraversal. func (g *GraphTraversal) Store(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("store", args...) + g.GremlinLang.AddStep("store", args...) return g } // Subgraph adds the subgraph step to the GraphTraversal. func (g *GraphTraversal) Subgraph(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("subgraph", args...) + g.GremlinLang.AddStep("subgraph", args...) return g } // Substring adds the substring step to the GraphTraversal. func (g *GraphTraversal) Substring(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("substring", int32Args(args)...) + g.GremlinLang.AddStep("substring", int32Args(args)...) return g } // Sum adds the sum step to the GraphTraversal. func (g *GraphTraversal) Sum(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("sum", args...) + g.GremlinLang.AddStep("sum", args...) return g } // Tail adds the tail step to the GraphTraversal. func (g *GraphTraversal) Tail(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("tail", args...) + g.GremlinLang.AddStep("tail", args...) return g } // TimeLimit adds the timeLimit step to the GraphTraversal. func (g *GraphTraversal) TimeLimit(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("timeLimit", args...) + g.GremlinLang.AddStep("timeLimit", args...) return g } // Times adds the times step to the GraphTraversal. func (g *GraphTraversal) Times(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("times", int32Args(args)...) + g.GremlinLang.AddStep("times", int32Args(args)...) return g } // To adds the to step to the GraphTraversal. func (g *GraphTraversal) To(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("to", args...) + g.GremlinLang.AddStep("to", args...) return g } // ToE adds the toE step to the GraphTraversal. func (g *GraphTraversal) ToE(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("toE", args...) + g.GremlinLang.AddStep("toE", args...) return g } // ToLower adds the toLower step to the GraphTraversal. func (g *GraphTraversal) ToLower(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("toLower", args...) + g.GremlinLang.AddStep("toLower", args...) return g } // ToUpper adds the toUpper step to the GraphTraversal. func (g *GraphTraversal) ToUpper(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("toUpper", args...) + g.GremlinLang.AddStep("toUpper", args...) return g } // ToV adds the toV step to the GraphTraversal. func (g *GraphTraversal) ToV(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("toV", args...) + g.GremlinLang.AddStep("toV", args...) return g } // Tree adds the tree step to the GraphTraversal. func (g *GraphTraversal) Tree(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("tree", args...) + g.GremlinLang.AddStep("tree", args...) return g } // Trim adds the tree step to the GraphTraversal. func (g *GraphTraversal) Trim(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("trim", args...) + g.GremlinLang.AddStep("trim", args...) return g } // Unfold adds the unfold step to the GraphTraversal. func (g *GraphTraversal) Unfold(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("unfold", args...) + g.GremlinLang.AddStep("unfold", args...) return g } // Union adds the union step to the GraphTraversal. func (g *GraphTraversal) Union(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("union", args...) + g.GremlinLang.AddStep("union", args...) return g } // Until adds the until step to the GraphTraversal. func (g *GraphTraversal) Until(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("until", args...) + g.GremlinLang.AddStep("until", args...) return g } // Value adds the value step to the GraphTraversal. func (g *GraphTraversal) Value(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("value", args...) + g.GremlinLang.AddStep("value", args...) return g } // ValueMap adds the valueMap step to the GraphTraversal. func (g *GraphTraversal) ValueMap(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("valueMap", args...) + g.GremlinLang.AddStep("valueMap", args...) return g } // Values adds the values step to the GraphTraversal. func (g *GraphTraversal) Values(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("values", args...) + g.GremlinLang.AddStep("values", args...) return g } // Where adds the where step to the GraphTraversal. func (g *GraphTraversal) Where(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("where", args...) + g.GremlinLang.AddStep("where", args...) return g } // With adds the with step to the GraphTraversal. func (g *GraphTraversal) With(args ...interface{}) *GraphTraversal { // Force int32 serialization for valid number values for server compatibility - g.Bytecode.AddStep("with", int32Args(args)...) + g.GremlinLang.AddStep("with", int32Args(args)...) return g } // Write adds the write step to the GraphTraversal. func (g *GraphTraversal) Write(args ...interface{}) *GraphTraversal { - g.Bytecode.AddStep("write", args...) + g.GremlinLang.AddStep("write", args...) return g } @@ -922,7 +925,7 @@ func (t *Transaction) Begin() (*GraphTraversalSource, error) { gts := &GraphTraversalSource{ graph: t.g.graph, - bytecode: t.g.bytecode, + gremlinLang: t.g.gremlinLang, remoteConnection: t.sessionBasedConnection} return gts, nil } diff --git a/gremlin-go/driver/graphTraversalSource.go b/gremlin-go/driver/graphTraversalSource.go index 31ee2d4be7..a93e7768ed 100644 --- a/gremlin-go/driver/graphTraversalSource.go +++ b/gremlin-go/driver/graphTraversalSource.go @@ -30,7 +30,7 @@ func convertStrategyVarargs(strategies []TraversalStrategy) []interface{} { // GraphTraversalSource can be used to start GraphTraversal. type GraphTraversalSource struct { graph *Graph - bytecode *Bytecode + gremlinLang *GremlinLang remoteConnection *DriverRemoteConnection graphTraversal *GraphTraversal } @@ -39,34 +39,34 @@ type GraphTraversalSource struct { // Graph and DriverRemoteConnection can be set to nil as valid default values. func NewGraphTraversalSource(graph *Graph, remoteConnection *DriverRemoteConnection, traversalStrategies ...TraversalStrategy) *GraphTraversalSource { - convertedArgs := convertStrategyVarargs(traversalStrategies) - bc := NewBytecode(nil) - bc.AddSource("withStrategies", convertedArgs...) - return &GraphTraversalSource{graph: graph, bytecode: bc, remoteConnection: remoteConnection} + // TODO: revisit when updating strategies + gl := NewGremlinLang(nil) + return &GraphTraversalSource{graph: graph, gremlinLang: gl, remoteConnection: remoteConnection} } // NewDefaultGraphTraversalSource creates a new graph GraphTraversalSource without a graph, strategy, or existing traversal. func NewDefaultGraphTraversalSource() *GraphTraversalSource { - return &GraphTraversalSource{graph: nil, bytecode: NewBytecode(nil), remoteConnection: nil} + return &GraphTraversalSource{graph: nil, gremlinLang: NewGremlinLang(nil), remoteConnection: nil} } // GetBytecode gets the traversal Bytecode associated with this graph traversal source. +// TODO remove func (gts *GraphTraversalSource) GetBytecode() *Bytecode { - return gts.bytecode + return nil } // GetGraphTraversal gets the graph traversal associated with this graph traversal source. func (gts *GraphTraversalSource) GetGraphTraversal() *GraphTraversal { - return NewGraphTraversal(gts.graph, NewBytecode(gts.bytecode), gts.remoteConnection) + return NewGraphTraversal(gts.graph, NewGremlinLang(gts.gremlinLang), gts.remoteConnection) } func (gts *GraphTraversalSource) clone() *GraphTraversalSource { - return cloneGraphTraversalSource(gts.graph, NewBytecode(gts.bytecode), gts.remoteConnection) + return cloneGraphTraversalSource(gts.graph, NewGremlinLang(gts.gremlinLang), gts.remoteConnection) } -func cloneGraphTraversalSource(graph *Graph, bc *Bytecode, remoteConnection *DriverRemoteConnection) *GraphTraversalSource { +func cloneGraphTraversalSource(graph *Graph, gl *GremlinLang, remoteConnection *DriverRemoteConnection) *GraphTraversalSource { return &GraphTraversalSource{graph: graph, - bytecode: bc, + gremlinLang: gl, remoteConnection: remoteConnection, } } @@ -74,17 +74,14 @@ func cloneGraphTraversalSource(graph *Graph, bc *Bytecode, remoteConnection *Dri // WithBulk allows for control of bulking operations. func (gts *GraphTraversalSource) WithBulk(args ...interface{}) *GraphTraversalSource { source := gts.clone() - err := source.bytecode.AddSource("withBulk", args...) - if err != nil { - return nil - } + source.gremlinLang.AddSource("withBulk", args...) return source } // WithPath adds a path to be used throughout the life of a spawned Traversal. func (gts *GraphTraversalSource) WithPath(args ...interface{}) *GraphTraversalSource { source := gts.clone() - source.bytecode.AddSource("withPath", args...) + source.gremlinLang.AddSource("withPath", args...) return source } @@ -92,14 +89,14 @@ func (gts *GraphTraversalSource) WithPath(args ...interface{}) *GraphTraversalSo func (gts *GraphTraversalSource) WithSack(args ...interface{}) *GraphTraversalSource { source := gts.clone() // Force int32 serialization for valid number values for server compatibility - source.bytecode.AddSource("withSack", int32Args(args)...) + source.gremlinLang.AddSource("withSack", int32Args(args)...) return source } // WithSideEffect adds a side effect to be used throughout the life of a spawned Traversal. func (gts *GraphTraversalSource) WithSideEffect(args ...interface{}) *GraphTraversalSource { source := gts.clone() - source.bytecode.AddSource("withSideEffect", args...) + source.gremlinLang.AddSource("withSideEffect", args...) return source } @@ -107,7 +104,7 @@ func (gts *GraphTraversalSource) WithSideEffect(args ...interface{}) *GraphTrave func (gts *GraphTraversalSource) WithStrategies(args ...TraversalStrategy) *GraphTraversalSource { convertedArgs := convertStrategyVarargs(args) source := gts.clone() - source.bytecode.AddSource("withStrategies", convertedArgs...) + source.gremlinLang.AddSource("withStrategies", convertedArgs...) return source } @@ -115,7 +112,7 @@ func (gts *GraphTraversalSource) WithStrategies(args ...TraversalStrategy) *Grap func (gts *GraphTraversalSource) WithoutStrategies(args ...TraversalStrategy) *GraphTraversalSource { convertedArgs := convertStrategyVarargs(args) source := gts.clone() - source.bytecode.AddSource("withoutStrategies", convertedArgs...) + source.gremlinLang.AddSource("withoutStrategies", convertedArgs...) return source } @@ -123,14 +120,8 @@ func (gts *GraphTraversalSource) WithoutStrategies(args ...TraversalStrategy) *G func (gts *GraphTraversalSource) With(key interface{}, value interface{}) *GraphTraversalSource { source := gts.clone() - var optionsStrategy TraversalStrategy = nil - for _, v := range gts.bytecode.sourceInstructions { - if v.operator == "withStrategies" && - v.arguments[0].(*traversalStrategy).name == decorationNamespace+"OptionsStrategy" { - optionsStrategy = v.arguments[0] - break - } - } + //TODO verify + var optionsStrategy TraversalStrategy = gts.gremlinLang.optionsStrategies[0] if optionsStrategy == nil { optionsStrategy = OptionsStrategy(map[string]interface{}{key.(string): value}) @@ -154,35 +145,35 @@ func (gts *GraphTraversalSource) WithRemote(remoteConnection *DriverRemoteConnec // E reads edges from the graph to start the traversal. func (gts *GraphTraversalSource) E(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("E", args...) + traversal.GremlinLang.AddStep("E", args...) return traversal } // V reads vertices from the graph to start the traversal. func (gts *GraphTraversalSource) V(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("V", args...) + traversal.GremlinLang.AddStep("V", args...) return traversal } // AddE adds an Edge to start the traversal. func (gts *GraphTraversalSource) AddE(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("addE", args...) + traversal.GremlinLang.AddStep("addE", args...) return traversal } // AddV adds a Vertex to start the traversal. func (gts *GraphTraversalSource) AddV(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("addV", args...) + traversal.GremlinLang.AddStep("addV", args...) return traversal } // Call starts the traversal by executing a procedure func (gts *GraphTraversalSource) Call(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("call", args...) + traversal.GremlinLang.AddStep("call", args...) return traversal } @@ -190,35 +181,35 @@ func (gts *GraphTraversalSource) Call(args ...interface{}) *GraphTraversal { func (gts *GraphTraversalSource) Inject(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() // Force int32 serialization for valid number values for server compatibility - traversal.Bytecode.AddStep("inject", int32Args(args)...) + traversal.GremlinLang.AddStep("inject", int32Args(args)...) return traversal } // Io adds the io steps to start the traversal. func (gts *GraphTraversalSource) Io(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("io", args...) + traversal.GremlinLang.AddStep("io", args...) return traversal } // MergeE uses an upsert-like operation to add an Edge to start the traversal. func (gts *GraphTraversalSource) MergeE(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("mergeE", args...) + traversal.GremlinLang.AddStep("mergeE", args...) return traversal } // MergeV uses an upsert-like operation to add a Vertex to start the traversal. func (gts *GraphTraversalSource) MergeV(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("mergeV", args...) + traversal.GremlinLang.AddStep("mergeV", args...) return traversal } // Union allows for a multi-branched start to a traversal. func (gts *GraphTraversalSource) Union(args ...interface{}) *GraphTraversal { traversal := gts.GetGraphTraversal() - traversal.Bytecode.AddStep("union", args...) + traversal.GremlinLang.AddStep("union", args...) return traversal } diff --git a/gremlin-go/driver/graphTraversalSource_test.go b/gremlin-go/driver/graphTraversalSource_test.go index f33c432d33..4c31423107 100644 --- a/gremlin-go/driver/graphTraversalSource_test.go +++ b/gremlin-go/driver/graphTraversalSource_test.go @@ -26,6 +26,7 @@ import ( func TestGraphTraversalSource(t *testing.T) { + // TODO update once option strategy application is property updated t.Run("GraphTraversalSource.With tests", func(t *testing.T) { t.Run("Test for single property", func(t *testing.T) { g := &GraphTraversalSource{graph: &Graph{}, bytecode: NewBytecode(nil), remoteConnection: nil} diff --git a/gremlin-go/driver/gremlinlang.go b/gremlin-go/driver/gremlinlang.go new file mode 100644 index 0000000000..66cdc20826 --- /dev/null +++ b/gremlin-go/driver/gremlinlang.go @@ -0,0 +1,513 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package gremlingo + +import ( + "fmt" + "math" + "math/big" + "reflect" + "strconv" + "strings" + "sync/atomic" +) + +type GremlinLang struct { + emptyArray []interface{} + gremlin *strings.Builder + parameters map[string]interface{} + optionsStrategies []*traversalStrategy + paramCount *atomic.Uint64 +} + +// NewGremlinLang creates a new GremlinLang to be used in traversals. +func NewGremlinLang(gl *GremlinLang) *GremlinLang { + gremlin := &strings.Builder{} + parameters := make(map[string]interface{}) + optionsStrategies := make([]*traversalStrategy, 0) + paramCount := atomic.Uint64{} + if gl != nil { + gremlin = gl.gremlin + parameters = gl.parameters + optionsStrategies = gl.optionsStrategies + paramCount.Store(gl.paramCount.Load()) + } + + return &GremlinLang{ + gremlin: gremlin, + parameters: parameters, + optionsStrategies: optionsStrategies, + paramCount: ¶mCount, + } +} + +func (gl *GremlinLang) addToGremlin(name string, args ...interface{}) error { + flattenedArgs := gl.flattenArguments(args...) + if name == "CardinalityValueTraversal" { + gl.gremlin.WriteString("Cardinality.") + str0, err := gl.argAsString(flattenedArgs[0]) + if err != nil { + return err + } + str1, err := gl.argAsString(flattenedArgs[1]) + if err != nil { + return err + } + gl.gremlin.WriteString(str0) + gl.gremlin.WriteString("(") + gl.gremlin.WriteString(str1) + gl.gremlin.WriteString(")") + } + + gl.gremlin.WriteString(".") + gl.gremlin.WriteString(name) + gl.gremlin.WriteString("(") + + for i := 0; i < len(flattenedArgs); i++ { + if i > 0 { + gl.gremlin.WriteString(",") + } + convertArg, err := gl.convertArgument(flattenedArgs[i]) //.Index(i).Interface()) + if err != nil { + return err + } + argStr, err := gl.argAsString(convertArg) + if err != nil { + return err + } + gl.gremlin.WriteString(argStr) + } + gl.gremlin.WriteString(")") + return nil +} + +func (gl *GremlinLang) argAsString(arg interface{}) (string, error) { + if arg == nil { + return "null", nil + } + // we are concerned with both single and double quotes and %q in fmt only escapes double quotes + escapeQuotes := strings.NewReplacer(`'`, `\'`, `"`, `\"`) + + switch v := arg.(type) { + case string: + return fmt.Sprintf("\"%s\"", escapeQuotes.Replace(v)), nil + case bool: + return strconv.FormatBool(v), nil + case uint8: + return fmt.Sprintf("%dB", v), nil + case int8, int16: + return fmt.Sprintf("%dS", v), nil + case int32, uint16: + return fmt.Sprintf("%d", v), nil + case int: + if v <= math.MaxInt32 && v >= math.MinInt32 { + return fmt.Sprintf("%d", v), nil + } else { + return fmt.Sprintf("%dL", v), nil + } + case int64, uint32: + return fmt.Sprintf("%dL", v), nil + case uint, uint64, *big.Int: + return fmt.Sprintf("%dN", v), nil + case float32: + if math.IsNaN(float64(v)) { + return "Nan", nil + } + if math.IsInf(float64(v), 1) { + return "Infinity", nil + } + if math.IsInf(float64(v), -1) { + return "-Infinity", nil + } + return fmt.Sprintf("%vF", v), nil + case float64: + if math.IsNaN(v) { + return "Nan", nil + } + if math.IsInf(v, 1) { + return "Infinity", nil + } + if math.IsInf(v, -1) { + return "-Infinity", nil + } + return fmt.Sprintf("%vD", v), nil + case *BigDecimal, BigDecimal: + return fmt.Sprintf("%vM", v), nil + case cardinality, column, direction, operator, order, pick, pop, barrier, scope, t, merge: + name := reflect.ValueOf(v).Type().Name() + return fmt.Sprintf("%s.%s", strings.ToUpper(name[:1])+name[1:], v), nil + case *Vertex: + id, _ := gl.argAsString(v.Id) + return fmt.Sprintf("new ReferenceVertex(%s,\"%s\")", escapeQuotes.Replace(id), escapeQuotes.Replace(v.Label)), nil + case textP: + return gl.translateTextPredicate(&v) + case *textP: + return gl.translateTextPredicate(v) + case p: + return gl.translatePredicate(&v) + case *p: + return gl.translatePredicate(v) + case Traversal: + gremlinLang := v.GremlinLang + for key, val := range gremlinLang.parameters { + gl.parameters[key] = val + } + return gremlinLang.GetGremlin("__"), nil + case *Traversal: + gremlinLang := v.GremlinLang + for key, val := range gremlinLang.parameters { + gl.parameters[key] = val + } + return gremlinLang.GetGremlin("__"), nil + case GraphTraversal: + gremlinLang := v.GremlinLang + for key, val := range gremlinLang.parameters { + gl.parameters[key] = val + } + return gremlinLang.GetGremlin("__"), nil + case *GraphTraversal: + gremlinLang := v.GremlinLang + for key, val := range gremlinLang.parameters { + gl.parameters[key] = val + } + return gremlinLang.GetGremlin("__"), nil + case GremlinLang: + for key, val := range v.parameters { + gl.parameters[key] = val + } + return v.GetGremlin("__"), nil + case *GremlinLang: + for key, val := range v.parameters { + gl.parameters[key] = val + } + return v.GetGremlin("__"), nil + default: + switch reflect.TypeOf(arg).Kind() { + case reflect.Map: + return gl.translateMap(arg) + case reflect.Slice: + return gl.translateSlice(arg) + default: + return gl.asParameter(arg), nil + } + } +} + +func (gl *GremlinLang) translateMap(arg interface{}) (string, error) { + sb := strings.Builder{} + sb.WriteString("[") + size := reflect.ValueOf(arg).Len() + if size == 0 { + sb.WriteString(":") + } else { + iter := reflect.ValueOf(arg).MapRange() + for iter.Next() { + k := iter.Key().Interface() + kString, err := gl.argAsString(k) + if err != nil { + return "", err + } + v := iter.Value().Interface() + vString, err := gl.argAsString(v) + if err != nil { + return "", err + } + sb.WriteString(kString) + sb.WriteByte(':') + sb.WriteString(vString) + size-- + if size > 0 { + sb.WriteString(",") + } + } + } + + sb.WriteString("]") + return sb.String(), nil +} + +func (gl *GremlinLang) translateSlice(arg interface{}) (string, error) { + sb := strings.Builder{} + sb.WriteString("[") + list := reflect.ValueOf(arg) + + for i := 0; i < list.Len(); i++ { + if i > 0 { + sb.WriteString(",") + } + vString, err := gl.argAsString(list.Index(i).Interface()) + if err != nil { + return "", err + } + sb.WriteString(vString) + } + sb.WriteString("]") + return sb.String(), nil +} + +func (gl *GremlinLang) translateTextPredicate(v *textP) (string, error) { + if v.operator == "" || len(v.values) == 0 { + return "", nil + } + + instructionString := "" + instructionString += v.operator + instructionString += "(" + if len(v.values) == 1 { + argString, err := gl.argAsString(v.values[0]) + if err != nil { + return "", err + } + instructionString += argString + } else if len(v.values) > 1 { + for index, arg := range v.values { + argString, err := gl.argAsString(arg) + if err != nil { + return "", err + } + + instructionString += argString + if index < len(v.values)-1 && argString != "" { + instructionString += "," + } + } + } + + instructionString += ")" + + return instructionString, nil +} + +func (gl *GremlinLang) translatePredicate(v *p) (string, error) { + + if v.operator == "" || len(v.values) == 0 { + return "", nil + } + + instructionString := "" + instructionString += v.operator + instructionString += "(" + if len(v.values) == 1 { + argString, err := gl.argAsString(v.values[0]) + if err != nil { + return "", err + } + instructionString += argString + } else if len(v.values) > 1 { + if v.operator != "between" && v.operator != "inside" { + instructionString += "[" + } + for index, arg := range v.values { + argString, err := gl.argAsString(arg) + if err != nil { + return "", err + } + + instructionString += argString + if index < len(v.values)-1 && argString != "" { + instructionString += "," + } + } + if v.operator != "between" && v.operator != "inside" { + instructionString += "]" + } + } + + instructionString += ")" + + return instructionString, nil +} +func (gl *GremlinLang) asParameter(arg interface{}) string { + paramName := fmt.Sprintf("_%d", gl.paramCount.Load()) + gl.paramCount.Add(1) + gl.parameters[paramName] = arg + return paramName +} + +func (gl *GremlinLang) GetGremlin(arg ...string) string { + var g string + gremlin := gl.gremlin.String() + if len(arg) == 0 { + g = "g" + } else { + g = arg[0] + } + // special handling for CardinalityValueTraversal + if gl.gremlin.Len() != 0 && string(gremlin[0]) != "." { + return gremlin + } + return g + gremlin +} + +func (gl *GremlinLang) GetParameters() map[string]interface{} { + return gl.parameters +} + +func (gl *GremlinLang) AddG(g string) { + gl.parameters["g"] = g +} + +func (gl *GremlinLang) Reset() { + gl.paramCount.Store(0) +} + +func (gl *GremlinLang) AddSource(name string, arguments ...interface{}) { + if name == "withStrategies" && len(arguments) != 0 { + args := gl.buildStrategyArgs(arguments...) + // possible to have empty strategies list to send + if len(args) != 0 { + gl.gremlin.WriteString(".withStrategies(") + gl.gremlin.WriteString(args) + gl.gremlin.WriteString(")") + } + return + } + gl.addToGremlin(name, arguments) +} + +func (gl *GremlinLang) buildStrategyArgs(args ...interface{}) string { + sb := strings.Builder{} + c := 0 + for _, arg := range args { + if c > 0 { + sb.WriteString(",") + } + strategy, ok := arg.(*traversalStrategy) + if !ok { + // error? + continue + } + // special handling for OptionsStrategy + if strategy.name == decorationNamespace+"OptionsStrategy" { + gl.optionsStrategies = append(gl.optionsStrategies, strategy) + continue + } + if len(strategy.configuration) == 0 { + sb.WriteString(strategy.name) + } else { + sb.WriteString("new ") + sb.WriteString(strategy.name) + sb.WriteString("(") + ct := 0 + for key, val := range strategy.configuration { + if ct > 0 { + sb.WriteString(",") + } + sb.WriteString(key) + sb.WriteString(":") + traversal, ok := val.(*Traversal) + if ok { + stringTraversal, _ := gl.argAsString(traversal.GremlinLang) + sb.WriteString(stringTraversal) + } else { + stringArg, _ := gl.argAsString(val) + sb.WriteString(stringArg) + } + ct++ + } + sb.WriteString(")") + } + c++ + } + return sb.String() +} + +func (gl *GremlinLang) AddStep(stepName string, arguments ...interface{}) error { + err := gl.addToGremlin(stepName, arguments) + return err +} + +func (gl *GremlinLang) GetOptionsStrategies() []*traversalStrategy { + return gl.optionsStrategies +} + +func (gl *GremlinLang) IsEmpty() bool { + return gl.gremlin.Len() == 0 +} + +func (gl *GremlinLang) flattenArguments(arguments ...interface{}) []interface{} { + if arguments == nil || len(arguments) == 0 { + return gl.emptyArray + } + flatArgs := make([]interface{}, 0) + for _, argument := range arguments { + arg, ok := argument.([]interface{}) + if ok { + for _, nestedArg := range arg { + converted, _ := gl.convertArgument(nestedArg) + flatArgs = append(flatArgs, converted) + } + } else { + converted, _ := gl.convertArgument(argument) + flatArgs = append(flatArgs, converted) + } + } + return flatArgs +} + +func (gl *GremlinLang) convertArgument(arg interface{}) (interface{}, error) { + if arg == nil { + return nil, nil + } + switch v := arg.(type) { + case *Traversal: + if v.graph != nil { + return nil, fmt.Errorf("the child traversal of %s was not spawned anonymously - "+ + "use the __ class rather than a TraversalSource to construct the child traversal", arg) + } + return v.GremlinLang, nil + default: + switch reflect.TypeOf(arg).Kind() { + case reflect.Map: + argMap := reflect.ValueOf(arg) + newMap := make(map[interface{}]interface{}, argMap.Len()) + for _, key := range argMap.MapKeys() { + convertKey, _ := gl.convertArgument(key.Interface()) + convertValue, _ := gl.convertArgument(argMap.MapIndex(key).Interface()) + newMap[convertKey] = convertValue + } + return newMap, nil + case reflect.Array, reflect.Slice: + argList := reflect.ValueOf(arg) + newList := make([]interface{}, argList.Len()) + for i := 0; i < argList.Len(); i++ { + convertValue, _ := gl.convertArgument(argList.Index(i).Interface()) + newList[i] = convertValue + } + return newList, nil + default: + return arg, nil + } + } +} + +// TODO revisit and remove if necessary +//var withOptionsMap map[any]string = map[any]string{ +// WithOptions.Tokens: "WithOptions.tokens", +// WithOptions.None: "WithOptions.none", +// WithOptions.Ids: "WithOptions.ids", +// WithOptions.Labels: "WithOptions.labels", +// WithOptions.Keys: "WithOptions.keys", +// WithOptions.Values: "WithOptions.values", +// WithOptions.All: "WithOptions.all", +// WithOptions.Indexer: "WithOptions.indexer", +// WithOptions.List: "WithOptions.list", +// WithOptions.Map: "WithOptions.map", +//} diff --git a/gremlin-go/driver/gremlinlang_test.go b/gremlin-go/driver/gremlinlang_test.go new file mode 100644 index 0000000000..c4f3237a6e --- /dev/null +++ b/gremlin-go/driver/gremlinlang_test.go @@ -0,0 +1,717 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package gremlingo + +import ( + "fmt" + "regexp" + "testing" + "time" +) + +func Test_GremlinLang(t *testing.T) { + type test struct { + name string + assert func(g *GraphTraversalSource) *GraphTraversal + equals string + only bool + skip bool + wantErr bool + containsRandomClassParams bool + } + tests := []test{ + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V() }, + equals: "g.V()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V("1", "2", "3", "4") }, + equals: "g.V(\"1\",\"2\",\"3\",\"4\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V("3").ValueMap(true) }, + equals: "g.V(\"3\").valueMap(true)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().Constant(5) }, + equals: "g.V().constant(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().Constant(1.5) }, + equals: "g.V().constant(1.5D)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().Constant("Hello") }, + equals: "g.V().constant(\"Hello\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().HasLabel("airport").Limit(5) }, + equals: "g.V().hasLabel(\"airport\").limit(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().HasLabel(P.Within("a", "b", "c")) }, + equals: "g.V().hasLabel(within([\"a\",\"b\",\"c\"]))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport", "continent").Out().Limit(5) + }, + equals: "g.V().hasLabel(\"airport\",\"continent\").out().limit(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Out().Values("code").Limit(5) + }, + equals: "g.V().hasLabel(\"airport\").out().values(\"code\").limit(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").As("a").Out("route").Limit(10).Where(P.Eq("a")).By("region") + }, + equals: "g.V(\"3\").as(\"a\").out(\"route\").limit(10).where(eq(\"a\")).by(\"region\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Repeat(T__.Out("route").SimplePath()).Times(2).Path().By("code") + }, + equals: "g.V(\"3\").repeat(__.out(\"route\").simplePath()).times(2).path().by(\"code\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Out().Has("region", "US-TX").Values("code").Limit(5) + }, + equals: "g.V().hasLabel(\"airport\").out().has(\"region\",\"US-TX\").values(\"code\").limit(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Union(T__.Values("city"), T__.Values("region")).Limit(5) + }, + equals: "g.V().hasLabel(\"airport\").union(__.values(\"city\"),__.values(\"region\")).limit(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V("3").As("a").Out("route", "routes") }, + equals: "g.V(\"3\").as(\"a\").out(\"route\",\"routes\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().Where(T__.Values("runways").Is(5)) }, + equals: "g.V().where(__.values(\"runways\").is(5))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Repeat(T__.Out().SimplePath()).Until(T__.Has("code", "AGR")).Path().By("code").Limit(5) + }, + equals: "g.V(\"3\").repeat(__.out().simplePath()).until(__.has(\"code\",\"AGR\")).path().by(\"code\").limit(5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().HasLabel("airport").Order().By(T__.Id()) }, + equals: "g.V().hasLabel(\"airport\").order().by(__.id())", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { return g.V().HasLabel("airport").Order().By(T.Id) }, + equals: "g.V().hasLabel(\"airport\").order().by(T.id)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Order().By(T__.Id(), Order.Desc) + }, + equals: "g.V().hasLabel(\"airport\").order().by(__.id(),Order.desc)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Order().By("code", Order.Desc) + }, + equals: "g.V().hasLabel(\"airport\").order().by(\"code\",Order.desc)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("1", "2", "3").Local(T__.Out().Out().Dedup().Fold()) + }, + equals: "g.V(\"1\",\"2\",\"3\").local(__.out().out().dedup().fold())", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Out().Path().Count(Scope.Local) + }, + equals: "g.V(\"3\").out().path().count(Scope.local)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.E().Count() + }, + equals: "g.E().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("5").OutE("route").InV().Path().Limit(10) + }, + equals: "g.V(\"5\").outE(\"route\").inV().path().limit(10)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("5").PropertyMap().Select(Column.Keys) + }, + equals: "g.V(\"5\").propertyMap().select(Column.keys)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("5").PropertyMap().Select(Column.Values) + }, + equals: "g.V(\"5\").propertyMap().select(Column.values)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Values("runways").Math("_ + 1") + }, + equals: "g.V(\"3\").values(\"runways\").math(\"_ + 1\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Emit().Repeat(T__.Out().SimplePath()).Times(3).Limit(5).Path() + }, + equals: "g.V(\"3\").emit().repeat(__.out().simplePath()).times(3).limit(5).path()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Match(T__.As("a").Has("code", "LHR").As("b")).Select("b").By("code") + }, + equals: "g.V().match(__.as(\"a\").has(\"code\",\"LHR\").as(\"b\")).select(\"b\").by(\"code\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("test-using-keyword-as-property", "repeat") + }, + equals: "g.V().has(\"test-using-keyword-as-property\",\"repeat\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("1").AddE("test").To(T__.V("4")) + }, + equals: "g.V(\"1\").addE(\"test\").to(__.V(\"4\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Values("runways").Max() + }, + equals: "g.V().values(\"runways\").max()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Values("runways").Min() + }, + equals: "g.V().values(\"runways\").min()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Values("runways").Sum() + }, + equals: "g.V().values(\"runways\").sum()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Values("runways").Mean() + }, + equals: "g.V().values(\"runways\").mean()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithSack(0).V("3", "5").Sack(Operator.Sum).By("runways").Sack() + }, + equals: "g.withSack(0).V(\"3\",\"5\").sack(Operator.sum).by(\"runways\").sack()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Values("runways").Store("x").V("4").Values("runways").Store("x").By(T__.Constant(1)).V("6").Store("x").By(T__.Constant(1)).Select("x").Unfold().Sum() + }, + equals: "g.V(\"3\").values(\"runways\").store(\"x\").V(\"4\").values(\"runways\").store(\"x\").by(__.constant(1)).V(\"6\").store(\"x\").by(__.constant(1)).select(\"x\").unfold().sum()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.Inject(3, 4, 5) + }, + equals: "g.inject(3,4,5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.Inject([]interface{}{3, 4, 5}) + }, + equals: "g.inject([3,4,5])", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.Inject(3, 4, 5).Count() + }, + equals: "g.inject(3,4,5).count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("runways", P.Gt(5)).Count() + }, + equals: "g.V().has(\"runways\",gt(5)).count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("runways", P.Lte(5.3)).Count() + }, + equals: "g.V().has(\"runways\",lte(5.3D)).count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("code", P.Within(123, 124)) + }, + equals: "g.V().has(\"code\",within([123,124]))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("code", P.Within(123, "abc")) + }, + equals: "g.V().has(\"code\",within([123,\"abc\"]))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("code", P.Within("abc", 123)) + }, + equals: "g.V().has(\"code\",within([\"abc\",123]))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("code", P.Within("abc", "xyz")) + }, + equals: "g.V().has(\"code\",within([\"abc\",\"xyz\"]))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("1", "2").Has("region", P.Within("US-TX", "US-GA")) + }, + equals: "g.V(\"1\",\"2\").has(\"region\",within([\"US-TX\",\"US-GA\"]))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().And(T__.Has("runways", P.Gt(5)), T__.Has("region", "US-TX")) + }, + equals: "g.V().and(__.has(\"runways\",gt(5)),__.has(\"region\",\"US-TX\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Union(T__.Has("runways", P.Gt(5)), T__.Has("region", "US-TX")) + }, + equals: "g.V().union(__.has(\"runways\",gt(5)),__.has(\"region\",\"US-TX\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Choose(T__.Values("runways").Is(3), T__.Constant("three"), T__.Constant("not three")) + }, + equals: "g.V(\"3\").choose(__.values(\"runways\").is(3),__.constant(\"three\"),__.constant(\"not three\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Choose(T__.Values("runways")).Option(1, T__.Constant("three")).Option(2, T__.Constant("not three")) + }, + equals: "g.V(\"3\").choose(__.values(\"runways\")).option(1,__.constant(\"three\")).option(2,__.constant(\"not three\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Choose(T__.Values("runways")).Option(1.5, T__.Constant("one and a half")).Option(2, T__.Constant("not three")) + }, + equals: "g.V(\"3\").choose(__.values(\"runways\")).option(1.5D,__.constant(\"one and a half\")).option(2,__.constant(\"not three\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Repeat(T__.Out().SimplePath()).Until(T__.Loops().Is(1)).Count() + }, + equals: "g.V(\"3\").repeat(__.out().simplePath()).until(__.loops().is(1)).count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Limit(20).Group().By("region").By("code").Order(Scope.Local).By(Column.Keys) + }, + equals: "g.V().hasLabel(\"airport\").limit(20).group().by(\"region\").by(\"code\").order(Scope.local).by(Column.keys)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("1").As("a").V("2").As("a").Select(Pop.All, "a") + }, + equals: "g.V(\"1\").as(\"a\").V(\"2\").as(\"a\").select(Pop.all,\"a\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddV("test").Property(Cardinality.Set, "p1", 10) + }, + equals: "g.addV(\"test\").property(Cardinality.set,\"p1\",10)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddV("test").Property(Cardinality.List, "p1", 10) + }, + equals: "g.addV(\"test\").property(Cardinality.list,\"p1\",10)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddV("test").Property(Cardinality.Single, "p1", 10) + }, + equals: "g.addV(\"test\").property(Cardinality.single,\"p1\",10)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Limit(5).Order().By(T__.Label()) + }, + equals: "g.V().limit(5).order().by(__.label())", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Range(1, 5) + }, + equals: "g.V().range(1,5)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddV("test").Property("p1", 123) + }, + equals: "g.addV(\"test\").property(\"p1\",123)", + }, + { + 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(new Date(121,1,1,9,30,0)))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddE("route").From(T__.V("1")).To(T__.V("2")) + }, + equals: "g.addE(\"route\").from(__.V(\"1\")).to(__.V(\"2\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithSideEffect("a", []interface{}{1, 2}).V("3").Select("a") + }, + equals: "g.withSideEffect(\"a\",[1,2]).V(\"3\").select(\"a\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithSideEffect("a", 1).V("3").Select("a") + }, + equals: "g.withSideEffect(\"a\",1).V(\"3\").select(\"a\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithSideEffect("a", "abc").V("3").Select("a") + }, + equals: "g.withSideEffect(\"a\",\"abc\").V(\"3\").select(\"a\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("airport", "region", "US-NM").Limit(3).Values("elev").Fold().Index() + }, + equals: "g.V().has(\"airport\",\"region\",\"US-NM\").limit(3).values(\"elev\").fold().index()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Repeat(T__.TimeLimit(1000).Out().SimplePath()).Until(T__.Has("code", "AGR")).Path() + }, + equals: "g.V(\"3\").repeat(__.timeLimit(1000).out().simplePath()).until(__.has(\"code\",\"AGR\")).path()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Where(T__.Values("elev").Is(P.Gt(14000))) + }, + equals: "g.V().hasLabel(\"airport\").where(__.values(\"elev\").is(gt(14000)))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Where(T__.Out().Count().Is(P.Gt(250))).Values("code") + }, + equals: "g.V().hasLabel(\"airport\").where(__.out().count().is(gt(250))).values(\"code\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().HasLabel("airport").Filter(T__.Out().Count().Is(P.Gt(250))).Values("code") + }, + equals: "g.V().hasLabel(\"airport\").filter(__.out().count().is(gt(250))).values(\"code\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithSack(0). + V("3"). + Repeat(T__.OutE("route").Sack(Operator.Sum).By("dist").InV()). + Until(T__.Has("code", "AGR").Or().Loops().Is(4)). + Has("code", "AGR"). + Local(T__.Union(T__.Path().By("code").By("dist"), T__.Sack()).Fold()). + Limit(10) + }, + equals: "g.withSack(0).V(\"3\").repeat(__.outE(\"route\").sack(Operator.sum).by(\"dist\").inV()).until(__.has(\"code\",\"AGR\").or().loops().is(4)).has(\"code\",\"AGR\").local(__.union(__.path().by(\"code\").by(\"dist\"),__.sack()).fold()).limit(10)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddV().As("a").AddV().As("b").AddE("knows").From("a").To("b") + }, + equals: "g.addV().as(\"a\").addV().as(\"b\").addE(\"knows\").from(\"a\").to(\"b\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.AddV("Person").As("a").AddV("Person").As("b").AddE("knows").From("a").To("b") + }, + equals: "g.addV(\"Person\").as(\"a\").addV(\"Person\").as(\"b\").addE(\"knows\").from(\"a\").to(\"b\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("3").Project("Out", "In").By(T__.Out().Count()).By(T__.In().Count()) + }, + equals: "g.V(\"3\").project(\"Out\",\"In\").by(__.out().count()).by(__.in().count())", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").Out().Aggregate("a").Out().Where(P.Within("a")).Path() + }, + equals: "g.V(\"44\").out().aggregate(\"a\").out().where(within(\"a\")).path()", + }, + { + 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\",new Date(121,2,22,0,0,0))", + }, + { + 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([new Date(121,2,22,0,0,0),new Date(121,1,1,0,0,0)]))", + }, + { + 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(new Date(121,1,1,0,0,0),new Date(121,2,22,0,0,0)))", + }, + { + 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(new Date(121,1,1,0,0,0),new Date(121,2,22,0,0,0)))", + }, + { + 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(new Date(121,1,1,9,30,0)))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("runways", P.Between(3, 5)) + }, + equals: "g.V().has(\"runways\",between(3,5))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("runways", P.Inside(3, 5)) + }, + equals: "g.V().has(\"runways\",inside(3,5))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").OutE().ElementMap() + }, + equals: "g.V(\"44\").outE().elementMap()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").ValueMap().By(T__.Unfold()) + }, + equals: "g.V(\"44\").valueMap().by(__.unfold())", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").ValueMap().With(WithOptions.Tokens, WithOptions.Labels) + }, + equals: "g.V(\"44\").valueMap().with(\"~tinkerpop.valueMap.tokens\",2)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").ValueMap().With(WithOptions.All) + }, + equals: "g.V(\"44\").valueMap().with(15)", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").ValueMap().With(WithOptions.Indexer) + }, + equals: "g.V(\"44\").valueMap().with(\"~tinkerpop.index.indexer\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V("44").ValueMap().With(WithOptions.Tokens) + }, + equals: "g.V(\"44\").valueMap().with(\"~tinkerpop.valueMap.tokens\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(ReadOnlyStrategy()).AddV("test") + }, + equals: "g.withStrategies(new ReadOnlyStrategy()).addV(\"test\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(SubgraphStrategy(SubgraphStrategyConfig{Vertices: T__.Has("region", "US-TX"), Edges: T__.HasLabel("route")})).V().Count() + }, + containsRandomClassParams: true, + equals: "g.withStrategies(new SubgraphStrategy(vertices:__.has(\"region\",\"US-TX\"),edges:__.hasLabel(\"route\"))).V().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(SubgraphStrategy(SubgraphStrategyConfig{VertexProperties: T__.HasNot("runways")})).V().Count() + }, + equals: "g.withStrategies(new SubgraphStrategy(vertexProperties:__.hasNot(\"runways\"))).V().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(SubgraphStrategy(SubgraphStrategyConfig{Vertices: T__.Has("region", "US-TX"), VertexProperties: T__.HasNot("runways")})).V().Count() + }, + containsRandomClassParams: true, + equals: "g.withStrategies(new SubgraphStrategy(vertices:__.has(\"region\",\"US-TX\"),vertexProperties:__.hasNot(\"runways\"))).V().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(ReadOnlyStrategy(), SubgraphStrategy(SubgraphStrategyConfig{Vertices: T__.Has("region", "US-TX"), Edges: T__.HasLabel("route")})).V().Count() + }, + containsRandomClassParams: true, + equals: "g.withStrategies(new ReadOnlyStrategy(),new SubgraphStrategy(vertices:__.has(\"region\",\"US-TX\"),edges:__.hasLabel(\"route\"))).V().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(ReadOnlyStrategy(), SubgraphStrategy(SubgraphStrategyConfig{Vertices: T__.Has("region", "US-TX")})).V().Count() + }, + equals: "g.withStrategies(new ReadOnlyStrategy(),new SubgraphStrategy(vertices:__.has(\"region\",\"US-TX\"))).V().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(OptionsStrategy(map[string]interface{}{"evaluationTimeout": 500})).V().Count() + }, + equals: "g.withStrategies(new OptionsStrategy(evaluationTimeout:500)).V().count()", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(PartitionStrategy(PartitionStrategyConfig{PartitionKey: "partition", WritePartition: "a", ReadPartitions: NewSimpleSet("a")})).AddV("test") + }, + containsRandomClassParams: true, + equals: "g.withStrategies(new PartitionStrategy(includeMetaProperties:false,partitionKey:\"partition\",writePartition:\"a\",readPartitions:[\"a\"])).addV(\"test\")", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.WithStrategies(VertexProgramStrategy(VertexProgramStrategyConfig{})).V().ShortestPath().With("~tinkerpop.shortestPath.target", T__.Has("name", "peter")) + }, + equals: "g.withStrategies(new VertexProgramStrategy()).V().shortestPath().with(\"~tinkerpop.shortestPath.target\",__.has(\"name\",\"peter\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("p1", TextP.StartingWith("foo")) + }, + equals: "g.V().has(\"p1\",startingWith(\"foo\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("p1", TextP.EndingWith("foo")) + }, + equals: "g.V().has(\"p1\",endingWith(\"foo\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("p1", TextP.Containing("foo")) + }, + equals: "g.V().has(\"p1\",containing(\"foo\"))", + }, + { + assert: func(g *GraphTraversalSource) *GraphTraversal { + return g.V().Has("p1", nil) + }, + equals: "g.V().has(\"p1\",null)", + }, + } + + var testsToRun []test + + onlyTests := make([]test, 0) + for _, tt := range tests { + if tt.only { + onlyTests = append(onlyTests, tt) + } + } + + if len(onlyTests) > 0 { + testsToRun = onlyTests + } else { + testsToRun = tests + } + + for _, tt := range testsToRun { + if tt.skip { + continue + } + + testName := tt.name + if testName == "" { + testName = tt.equals + } + + t.Run(testName, func(t *testing.T) { + g := NewGraphTraversalSource(nil, nil) + gremlinLang := tt.assert(g).GremlinLang.GetGremlin() + fmt.Println("---gremlin lang???") + fmt.Println(gremlinLang) + if !tt.containsRandomClassParams && gremlinLang != tt.equals { + t.Errorf("GremlinLang = %v, equals %v", gremlinLang, tt.equals) + } + if tt.containsRandomClassParams { + equalsParams := getArgs(tt.equals) + gotParams := getArgs(gremlinLang) + + if len(equalsParams) != len(gotParams) { + t.Errorf("GremlinLang = %v, equals %v", gremlinLang, tt.equals) + } + + for _, equalsParam := range equalsParams { + found := false + for _, gotParam := range gotParams { + if equalsParam == gotParam { + found = true + break + } + } + if !found { + t.Errorf("translator.Translate() = %v, equals %v", gremlinLang, tt.equals) + } + } + } + }) + } +} + +func getArgs(result string) []string { + pattern := `(\w+:.*?)` + re := regexp.MustCompile(pattern) + matches := re.FindAllStringSubmatch(result, -1) + + params := make([]string, 0) + for _, match := range matches { + if len(match) > 0 { + params = append(params, match[0]) + } + } + + return params +} diff --git a/gremlin-go/driver/strategies.go b/gremlin-go/driver/strategies.go index a2573c5fcc..d47636ee4c 100644 --- a/gremlin-go/driver/strategies.go +++ b/gremlin-go/driver/strategies.go @@ -399,7 +399,7 @@ func RemoteStrategy(connection DriverRemoteConnection) TraversalStrategy { return } - rs, err := connection.submitBytecode(g.Bytecode) + rs, err := connection.submitGremlinLang(g.GremlinLang) if err != nil { return } diff --git a/gremlin-go/driver/traversal.go b/gremlin-go/driver/traversal.go index ea1ccd4baf..83fb19f2a5 100644 --- a/gremlin-go/driver/traversal.go +++ b/gremlin-go/driver/traversal.go @@ -31,10 +31,11 @@ type Traverser struct { // Traversal is the primary way in which graphs are processed. type Traversal struct { - graph *Graph - Bytecode *Bytecode - remote *DriverRemoteConnection - results ResultSet + graph *Graph + Bytecode *Bytecode + GremlinLang *GremlinLang + remote *DriverRemoteConnection + results ResultSet } // ToList returns the result in a list. @@ -43,7 +44,8 @@ func (t *Traversal) ToList() ([]*Result, error) { return nil, newError(err0901ToListAnonTraversalError) } - results, err := t.remote.submitBytecode(t.Bytecode) + // TODO update and test when connection is set up + results, err := t.remote.submitGremlinLang(t.GremlinLang) if err != nil { return nil, err } @@ -76,12 +78,10 @@ func (t *Traversal) Iterate() <-chan error { return } - if err := t.Bytecode.AddStep("discard"); err != nil { - r <- err - return - } + t.GremlinLang.AddStep("discard") - res, err := t.remote.submitBytecode(t.Bytecode) + // TODO update and test when connection is set up + res, err := t.remote.submitGremlinLang(t.GremlinLang) if err != nil { r <- err return @@ -120,7 +120,8 @@ func (t *Traversal) Next() (*Result, error) { // GetResultSet submits the traversal and returns the ResultSet. func (t *Traversal) GetResultSet() (ResultSet, error) { if t.results == nil { - results, err := t.remote.submitBytecode(t.Bytecode) + // TODO update and test when connection is set up + results, err := t.remote.submitGremlinLang(t.GremlinLang) if err != nil { return nil, err } diff --git a/gremlin-go/driver/traversal_test.go b/gremlin-go/driver/traversal_test.go index 162936603c..21cc75af1e 100644 --- a/gremlin-go/driver/traversal_test.go +++ b/gremlin-go/driver/traversal_test.go @@ -31,7 +31,7 @@ import ( func TestTraversal(t *testing.T) { t.Run("Test clone traversal", func(t *testing.T) { - g := cloneGraphTraversalSource(&Graph{}, NewBytecode(nil), nil) + g := cloneGraphTraversalSource(&Graph{}, NewBytecode(nil), NewGremlinLang(nil), nil) original := g.V().Out("created") clone := original.Clone().Out("knows") cloneClone := clone.Clone().Out("created") @@ -56,7 +56,7 @@ func TestTraversal(t *testing.T) { }) t.Run("Test traversal with bindings", func(t *testing.T) { - g := cloneGraphTraversalSource(&Graph{}, NewBytecode(nil), nil) + g := cloneGraphTraversalSource(&Graph{}, NewBytecode(nil), NewGremlinLang(nil), nil) bytecode := g.V((&Bindings{}).Of("a", []int32{1, 2, 3})). Out((&Bindings{}).Of("b", "created")). Where(T__.In((&Bindings{}).Of("c", "created"), (&Bindings{}).Of("d", "knows")). diff --git a/gremlin-go/examples/go.mod b/gremlin-go/examples/go.mod index c3a6c6de3c..873f669535 100644 --- a/gremlin-go/examples/go.mod +++ b/gremlin-go/examples/go.mod @@ -17,7 +17,7 @@ module example -go 1.22 +go 1.22.0 require github.com/apache/tinkerpop/gremlin-go/v3 v3.7.1 diff --git a/gremlin-go/go.mod b/gremlin-go/go.mod index c0456f2363..8fdbf98bc1 100644 --- a/gremlin-go/go.mod +++ b/gremlin-go/go.mod @@ -17,7 +17,7 @@ module github.com/apache/tinkerpop/gremlin-go/v3 -go 1.22 +go 1.22.0 require ( github.com/cucumber/godog v0.15.0
