You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2026/07/03 03:35:29 UTC
(tinkerpop) 01/01: Merge branch '3.8-dev'
This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 82eb611a85e53465d4bb91550cc9d98917c29da4
Merge: 4ea917bd9b 1b288dcac8
Author: Cole Greer <co...@colegreer.ca>
AuthorDate: Thu Jul 2 20:04:06 2026 -0700
Merge branch '3.8-dev'
.gitignore | 3 +-
bin/process-docs.sh | 316 +++++++--
bin/validate-distribution.sh | 2 +-
docs/postprocessor/postprocess.sh | 38 --
docs/postprocessor/processor.awk | 53 --
docs/preprocessor/awk/cleanup.awk | 36 -
docs/preprocessor/awk/ignore.awk | 23 -
docs/preprocessor/awk/init-code-blocks.awk | 71 --
docs/preprocessor/awk/language-variants.awk | 44 --
docs/preprocessor/awk/prepare.awk | 83 ---
docs/preprocessor/awk/progressbar.awk | 36 -
docs/preprocessor/awk/tabify.awk | 132 ----
docs/preprocessor/control-characters.sh | 25 -
docs/preprocessor/install-plugins.groovy | 44 --
docs/preprocessor/install-plugins.sh | 74 --
docs/preprocessor/preprocess-file.sh | 161 -----
docs/preprocessor/preprocess.sh | 150 -----
docs/preprocessor/uninstall-plugins.sh | 36 -
.../dev/developer/development-environment.asciidoc | 135 ++--
docs/src/dev/developer/for-committers.asciidoc | 6 +-
docs/src/recipes/olap-spark-yarn.asciidoc | 54 +-
docs/src/reference/gremlin-variants.asciidoc | 4 +
.../reference/implementations-hadoop-end.asciidoc | 7 +-
.../implementations-hadoop-start.asciidoc | 5 +-
docs/src/reference/implementations-spark.asciidoc | 3 +
docs/src/reference/index.asciidoc | 7 +-
docs/src/reference/the-traversal.asciidoc | 6 +-
.../language/corpus/DocumentationReader.java | 2 +-
pom.xml | 64 ++
tools/tinkerpop-docs/pom.xml | 77 +++
.../gremlin/docs/ConsoleRestartHandler.java | 43 ++
.../tinkerpop/gremlin/docs/GremlinConsole.java | 286 ++++++++
.../gremlin/docs/GremlinDocsExtension.java | 28 +-
.../gremlin/docs/GremlinPostprocessor.java | 71 ++
.../gremlin/docs/GremlinTreeprocessor.java | 745 +++++++++++++++++++++
.../docs/PluginDirectoryRestartHandler.java | 130 ++++
.../tinkerpop/gremlin/docs/TabbedHtmlBuilder.java | 291 ++++++++
...ciidoctor.jruby.extension.spi.ExtensionRegistry | 1 +
.../src/main/resources/hadoop-conf/core-site.xml | 33 +
.../resources/hadoop-conf/hadoop-docs.properties | 16 +-
.../tinkerpop/gremlin/docs/GremlinConsoleTest.java | 320 +++++++++
.../tinkerpop/gremlin/docs/GremlinDocsTest.java | 81 +++
.../gremlin/docs/GremlinPostprocessorTest.java | 103 +++
.../gremlin/docs/GremlinTreeprocessorTest.java | 629 +++++++++++++++++
.../tinkerpop/gremlin/docs/IntegrationTest.java | 131 ++++
.../docs/PluginDirectoryRestartHandlerTest.java | 138 ++++
.../gremlin/docs/TabbedHtmlBuilderTest.java | 286 ++++++++
.../test/resources/integration-fixture.asciidoc | 98 +++
48 files changed, 3901 insertions(+), 1226 deletions(-)
diff --cc docs/src/dev/developer/development-environment.asciidoc
index 62b431039f,33fae609df..e0a9559218
--- a/docs/src/dev/developer/development-environment.asciidoc
+++ b/docs/src/dev/developer/development-environment.asciidoc
@@@ -506,10 -484,10 +459,10 @@@ mvn -Dmaven.javadoc.skip=true --project
** Build AsciiDocs (but don't evaluate code blocks): `bin/process-docs.sh --dryRun`
** Build AsciiDocs (but don't evaluate code blocks in specific files): `bin/process-docs.sh --dryRun docs/src/reference/the-graph.asciidoc,docs/src/tutorial/getting-started,...`
** Build AsciiDocs (but evaluate code blocks only in specific files): `bin/process-docs.sh --fullRun docs/src/reference/the-graph.asciidoc,docs/src/tutorial/getting-started,...`
- ** Process a single AsciiDoc file: +pass:[docs/preprocessor/preprocess-file.sh `pwd`/gremlin-console/target/apache-tinkerpop-gremlin-console-*-standalone "" "*" `pwd`/docs/src/xyz.asciidoc]+
+ ** Process docs in dry-run mode (no console required): `bin/process-docs.sh --dryRun`
* Build JavaDocs/JSDoc: `mvn process-resources -Djavadoc`
** Javadoc to `target/site/apidocs` directory
-** JSDoc to the `gremlin-javascript/src/main/javascript/gremlin-javascript/doc/` directory
+** JSDoc to the `gremlin-js/gremlin-javascript/doc/` directory
* Specify the seed used for `Random` in tests `mvn clean install -DtestSeed` - useful when a test fails, the seed will be printed in the build output so that the test can run with the same version of random (look for "TestHelper" logger in output)
* Check for newer dependencies: `mvn versions:display-dependency-updates` or `mvn versions:display-plugin-updates`
* Check the effective `pom.xml`: `mvn -pl gremlin-python -Pglv-python help:effective-pom -Doutput=withProfilePom.xml`
diff --cc docs/src/recipes/olap-spark-yarn.asciidoc
index 31d118f61a,12ea3c77d0..481054233b
--- a/docs/src/recipes/olap-spark-yarn.asciidoc
+++ b/docs/src/recipes/olap-spark-yarn.asciidoc
@@@ -89,29 -89,44 +89,47 @@@ $ hdfs dfs -put data/tinkerpop-modern.k
$ . bin/spark-yarn.sh
----
+WARNING: The Hadoop and Spark modules are not included in the 4.0.0-beta.2 distribution. This recipe will
+be restored in a future release.
+
[source,groovy]
----
- hadoop = System.getenv('HADOOP_HOME')
- hadoopConfDir = System.getenv('HADOOP_CONF_DIR')
- archive = 'spark-gremlin.zip'
- archivePath = "/tmp/$archive"
- ['bash', '-c', "rm -f $archivePath; cd ext/spark-gremlin/lib && zip $archivePath *.jar"].execute().waitFor()
- conf = new Configurations().properties(new File('conf/hadoop/hadoop-gryo.properties'))
- conf.setProperty('spark.master', 'yarn')
- conf.setProperty('spark.submit.deployMode', 'client')
- conf.setProperty('spark.yarn.archive', "$archivePath")
- conf.setProperty('spark.yarn.appMasterEnv.CLASSPATH', "./__spark_libs__/*:$hadoopConfDir")
- conf.setProperty('spark.executor.extraClassPath', "./__spark_libs__/*:$hadoopConfDir")
- conf.setProperty('spark.driver.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
- conf.setProperty('spark.executor.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
- conf.setProperty('gremlin.spark.persistContext', 'true')
- hdfs.copyFromLocal('data/tinkerpop-modern.kryo', 'tinkerpop-modern.kryo')
- graph = GraphFactory.open(conf)
- g = traversal().with(graph).withComputer(SparkGraphComputer)
- g.V().group().by(values('name')).by(both().count())
+ gremlin> hadoop = System.getenv('HADOOP_HOME')
+ ==>/usr/local/lib/hadoop-3.3.1
+ gremlin> hadoopConfDir = System.getenv('HADOOP_CONF_DIR')
+ ==>/usr/local/lib/hadoop-3.3.1/etc/hadoop
+ gremlin> archive = 'spark-gremlin.zip'
+ ==>spark-gremlin.zip
+ gremlin> archivePath = "/tmp/$archive"
+ ==>/tmp/spark-gremlin.zip
+ gremlin> ['bash', '-c', "rm -f $archivePath; cd ext/spark-gremlin/lib && zip $archivePath *.jar"].execute().waitFor()
+ ==>0
+ gremlin> conf = new Configurations().properties(new File('conf/hadoop/hadoop-gryo.properties'))
+ ==>org.apache.commons.configuration2.PropertiesConfiguration@5b3bb1f7
+ gremlin> conf.setProperty('spark.master', 'yarn')
+ ==>null
+ gremlin> conf.setProperty('spark.submit.deployMode', 'client')
+ ==>null
+ gremlin> conf.setProperty('spark.yarn.archive', "$archivePath")
+ ==>null
+ gremlin> conf.setProperty('spark.yarn.appMasterEnv.CLASSPATH', "./__spark_libs__/*:$hadoopConfDir")
+ ==>null
+ gremlin> conf.setProperty('spark.executor.extraClassPath', "./__spark_libs__/*:$hadoopConfDir")
+ ==>null
+ gremlin> conf.setProperty('spark.driver.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
+ ==>null
+ gremlin> conf.setProperty('spark.executor.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
+ ==>null
+ gremlin> conf.setProperty('gremlin.spark.persistContext', 'true')
+ ==>null
+ gremlin> hdfs.copyFromLocal('data/tinkerpop-modern.kryo', 'tinkerpop-modern.kryo')
+ ==>null
+ gremlin> graph = GraphFactory.open(conf)
+ ==>hadoopgraph[gryoinputformat->gryooutputformat]
+ gremlin> g = traversal().withEmbedded(graph).withComputer(SparkGraphComputer)
+ ==>graphtraversalsource[hadoopgraph[gryoinputformat->gryooutputformat], sparkgraphcomputer]
+ gremlin> g.V().group().by(values('name')).by(both().count())
+ ==>[ripple:1,peter:1,vadas:1,josh:3,lop:3,marko:3]
----
If you run into exceptions, you will have to dig into the logs. You can do this from the command line with
diff --cc docs/src/reference/implementations-hadoop-end.asciidoc
index 008965b4cc,338792d6fe..57047d3e68
--- a/docs/src/reference/implementations-hadoop-end.asciidoc
+++ b/docs/src/reference/implementations-hadoop-end.asciidoc
@@@ -16,11 -16,11 +16,14 @@@ KIND, either express or implied. See t
specific language governing permissions and limitations
under the License.
////
+ // Continues the Spark/Hadoop OLAP examples (Scala 2.12), so exclude neo4j-gremlin (Scala 2.11)
+ // to keep it off the console's flat classpath.
+ [gremlin-docs-plugins-exclude="neo4j-gremlin"]
=== Input/Output Formats
+WARNING: The Hadoop and Spark modules are not included in the 4.0.0-beta.2 distribution. The examples in
+this section are presented as static code and will be restored in a future release.
+
image:adjacency-list.png[width=300,float=right] Hadoop-Gremlin provides various I/O formats -- i.e. Hadoop
`InputFormat` and `OutputFormat`. All of the formats make use of an link:http://en.wikipedia.org/wiki/Adjacency_list[adjacency list]
representation of the graph where each "row" represents a single vertex, its properties, and its incoming and
diff --cc docs/src/reference/implementations-hadoop-start.asciidoc
index f20f143388,bcc0c4bfb1..970b8ff462
--- a/docs/src/reference/implementations-hadoop-start.asciidoc
+++ b/docs/src/reference/implementations-hadoop-start.asciidoc
@@@ -145,13 -148,10 +148,13 @@@ WARNING: OLTP operations on `HadoopGrap
for large graphs. In such large graph situations, make use of <<traversalvertexprogram,TraversalVertexProgram>>
which is the OLAP Gremlin machine.
-[gremlin-groovy]
+WARNING: The Hadoop and Spark modules are not included in the 4.0.0-beta.2 distribution. These examples will
+be restored in a future release.
+
+[source,groovy]
----
hdfs.copyFromLocal('data/tinkerpop-modern.kryo', 'tinkerpop-modern.kryo')
- hdfs.ls()
+ hdfs.ls('tinkerpop-modern.kryo')
graph = GraphFactory.open('conf/hadoop/hadoop-gryo.properties')
g = traversal().with(graph)
g.V().count()
diff --cc docs/src/reference/index.asciidoc
index 104dd7c655,1bd8858574..2465fab0f5
--- a/docs/src/reference/index.asciidoc
+++ b/docs/src/reference/index.asciidoc
@@@ -41,10 -41,12 +41,11 @@@ include::gremlin-variants.asciidoc[
include::implementations-intro.asciidoc[]
include::implementations-tinkergraph.asciidoc[]
-include::implementations-neo4j.asciidoc[]
- // the hadoop section is split into parts because of serialization issues that are encountered when trying
- // to generate graph/spark without restarting the console and currently the only way to force a restart of the
- // console is to have a new asciidoc page.
+ // The hadoop section is split into parts so the Neo4j/Spark plugins (incompatible Scala versions)
+ // are not active at the same time. Console restarts are now driven by the
+ // :gremlin-docs-plugins-exclude: attribute on each chapter heading (see implementations-neo4j,
+ // implementations-hadoop-start, implementations-spark) rather than by page boundaries.
include::implementations-hadoop-start.asciidoc[]
include::implementations-spark.asciidoc[]
include::implementations-hadoop-end.asciidoc[]
diff --cc docs/src/reference/the-traversal.asciidoc
index 5db65c45db,efaf2d424f..393a458d5a
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@@ -3042,50 -2847,28 +3042,50 @@@ and pass the value in the params map vi
[gremlin-groovy,modern]
----
- g.match("MATCH (p:person {name: $personName})-[:knows]->(f:person)",
-traversal = g.V().match(
- __.as('a').has(label,'person'), <1>
- __.as('a').out('created').as('b'),
- __.as('b').in('created').as('c')).
- where(__.as('a').out('knows').as('c')). <2>
- select('a','c').by('name'); null <3>
-traversal.toString() <4>
-traversal <5> <6>
-traversal.toString() <7>
++g.match('MATCH (p:person {name: $personName})-[:knows]->(f:person)',
+ ["personName": "marko"]).
+ select("p", "f").by("name")
----
-<1> Any `has()`-step traversal patterns that start with the match-key are pulled out of `match()` to enable the graph
-system to leverage the filter for index lookups.
-<2> A `where()`-step with a traversal containing variable bindings declared in `match()`.
-<3> A useful trick to ensure that the traversal is not iterated by Gremlin Console.
-<4> The string representation of the traversal prior to its strategies being applied.
-<5> The Gremlin Console will automatically iterate anything that is an iterator or is iterable.
-<6> Both marko and josh are co-developers and marko knows josh.
-<7> The string representation of the traversal after the strategies have been applied (and thus, `where()` is folded into `match()`)
+The parsed query graph is cached in an LRU cache (up to 1,000 entries), so the same query string is parsed only
+once across calls. Edge-case parameter behaviors:
+
+[width="100%",cols="3,3",options="header"]
+|=========================================================
+|Situation |Result
+|Parameter key present, non-null value |Predicate tests the element property against the supplied value
+|Parameter key present, `null` value |Predicate passes only for elements where the property is absent
+|Parameter key absent from the map |Predicate always fails — no element matches that filter
+|Numeric type mismatch (e.g. `Integer` 29 vs `Long` 29) |Values are compared numerically; `29` (Integer) equals `29L` (Long)
+|=========================================================
+
+When the graph provides an implementation of `Graph.Index` (accessed via `graph.index()`), the executor
+automatically uses the index for seed vertex lookup, reducing the initial scan to only those vertices whose
+indexed property matches the filter value. This is especially effective when the parameterized query pattern is
+constant but the parameter values change across calls — the query graph is cached once and each invocation
+performs an index-backed seed lookup rather than a full scan. Whether `Graph.Index` is backed by a real index
+structure depends on the graph system; see <<tinkerpop-providers-tinkergql,the provider documentation>> and
+your specific graph system's documentation for details.
+
+===== Unsupported Features
+
+TinkerGQL is a minimal subset of ISO GQL. The following ISO GQL `MATCH` features are not yet implemented:
+
+[width="100%",cols="2,4",options="header"]
+|=========================================================
+|Feature |Notes
+|`WHERE` clause |Post-match filtering is not supported inside the `MATCH` string. Use Gremlin's `where()` step after `match()` instead.
+|`RETURN` clause |Projection inside the `MATCH` string is not supported. Use `select()` after `match()` to project named variables.
+|Inequality / range predicates |Only equality tests (`{key: value}`) are supported. Expressions like `n.age > 30` are not part of the grammar.
+|Variable-length paths |Quantified path patterns such as `(a)-[:KNOWS*1..3]->(b)` are not supported.
+|Multiple labels per element |`(n:Person:Employee)` — more than one label per node pattern — is not supported.
+|`OPTIONAL MATCH` |Optional pattern matching (outer joins) is not supported.
+|Aggregation functions |`COUNT`, `SUM`, `AVG`, and similar functions are not part of the grammar.
+|OLAP / GraphComputer mode |`match(String)` does not execute in OLAP (GraphComputer) mode. `GqlDeclarativeMatchStrategy` detects a graph-computer traversal context and exits without replacing the placeholder step, resulting in an `UnsupportedOperationException` at execution time.
+|=========================================================
-IMPORTANT: A `where()`-step is a filter and thus, variables within a `where()` clause are not globally bound to the
-path of the traverser in `match()`. As such, `where()`-steps in `match()` are used for filtering, not binding.
+Equivalent behaviour for `WHERE` and `RETURN` can be expressed using the standard Gremlin step vocabulary
+(`where()`, `select()`, `filter()`, `group()`, etc.).
*Additional References*
@@@ -4198,13 -3980,8 +4198,13 @@@ g.V(1).property(list, ['age': single(36
g.V(1).valueMap()
g.V(1).property('friendWeight',outE('knows').values('weight').sum(),'acl','private') <5>
g.V(1).properties('friendWeight').valueMap() <6>
-g.addV().property(T.label,'person').valueMap().with(WithOptions.tokens) <7>
-g.addV().property(null) <8>
+g.V(4).property(
+ __.V(1).project('friendCount', 'createdSoftware').
+ by(__.out('knows').count()).
+ by(__.out('created').values('name'))) <7>
+g.V(4).valueMap()
+g.addV().property(T.label,'person').valueMap().with(WithOptions.tokens) <8>
- g.addV().property(null) <9>
++g.addV().property((Map) null) <9>
g.addV().property(set, null)
----
diff --cc tools/tinkerpop-docs/pom.xml
index 0000000000,6c95a45e85..def3a70048
mode 000000,100644..100644
--- a/tools/tinkerpop-docs/pom.xml
+++ b/tools/tinkerpop-docs/pom.xml
@@@ -1,0 -1,77 +1,77 @@@
+ <!--
+ 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.
+ -->
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tinkerpop</groupId>
+ <artifactId>tinkerpop</artifactId>
- <version>3.8.2-SNAPSHOT</version>
++ <version>4.0.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <artifactId>tinkerpop-docs</artifactId>
+ <name>Apache TinkerPop :: Docs Extension</name>
+ <description>AsciidoctorJ extension for processing gremlin code blocks in TinkerPop documentation</description>
+ <packaging>jar</packaging>
+
+ <properties>
+ <asciidoctorj.version>2.5.13</asciidoctorj.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctorj</artifactId>
+ <version>${asciidoctorj.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest</artifactId>
+ <version>${hamcrest.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.14.0</version>
+ <configuration>
+ <!-- AsciidoctorJ 2.5.x requires Java 11+ -->
+ <release>11</release>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </project>