Hi Luca, for an embedded Graph the answer is fairly straightforward as we have a model for it already with graph.cypher():
https://github.com/apache/tinkerpop/blob/3.5.1/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java#L250-L272 So that's one way. The approach is a bit dated though because it's forcing the user to utilize the Graph instance to spawn the traversal and not the GraphTraversalSource and we've been discouraging that as of the last few years (i'd forgotten we'd done that this way until just now actually). Perhaps the more modern approach is better demonstrated by sparql-gremlin: https://github.com/apache/tinkerpop/blob/3.5.1/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/dsl/sparql/SparqlTraversalSource.java#L171-L181 but requires more infrastructure there because you need to construct a bit of boilerplate code to make that work: https://github.com/apache/tinkerpop/tree/3.5.1/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/dsl/sparql but it then allows for a proper start from g: gremlin> g = traversal(SparqlTraversalSource).withEmbedded(graph) ==>sparqltraversalsource[tinkergraph[vertices:6 edges:6], standard] gremlin> g.sparql("""SELECT ?name ?age WHERE { ?person v:name ?name . ?person v:age ?age } ORDER BY ASC(?age)""") ==>[name:vadas,age:27] ==>[name:marko,age:29] ==>[name:josh,age:32] ==>[name:peter,age:35] So, this works fine for embedded cases but comes with caveats to remote cases. If using Gremlin Server, you would need to have your library (with either approach implemented) available in the path. For the first approach via Graph, users could only access that by way of scripts sent to the server as in: https://tinkerpop.apache.org/docs/current/reference/#gremlin-java-scripts The same applies for the second approach with a custom GraphTraversalSource, but you can also have remote use cases if you implement just as we did with sparql-gremlin where a special TraversalStrategy is in place to handle the incoming SQL query (my link to the SparqlTraversalSource shows the entry point for that). In this case, the traversal will arrive as Gremlin bytecode where the SPARQL string is embedded inside an inject() and the SparqlStrategy basically detects that and uses the SPARQL string to its own ends: https://github.com/apache/tinkerpop/blob/3.5.1/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java Finally, note that a problem we've not yet solved is how a custom the sparql-gremlin approach would work nicely with non-JVM languages like Python. We'd have to implement that sparql() step in each programming language and of course it's not nice for providers who may want to offer their own extensions which would lead them to have to publish their own libraries for each programming language. We seem to need some sort of way to handle dynamic steps (or something like that) but that really hasn't been settled yet. On Tue, Aug 10, 2021 at 2:04 AM Luca Garulli <[email protected]> wrote: > Hi guys, > > I'd like to expose a new step *sql(String)* able to interpret a SQL string > with the return of a resultset of elements. > > What's the best way to do this? > > Also, when a client fires a gremlin query, is the query sent as a text to > the gremlin server to be interpreted only on the server side? > > Thanks, > Luca >
