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
>

Reply via email to