Edit on Github

Installation

Prerequisites

To use this client, you need a compatible version of TypeDB Server running. Please see the Compatibility Table to check what version do you need, depending on the TypeDB server version being used.

Add a repository with TypeDB Java client to Maven

Add the code below to the pom.xml file in your Maven project.

[Important] Be sure to replace the `{version}` placeholder tag with the version of Client Java you want to install.

<repositories>
    <repository>
        <id>repo.vaticle.com</id>
        <url>https://repo.vaticle.com/repository/maven/</url>
    </repository>
</repositories>
<dependencies>
<dependency>
    &lt;groupId&gt;com.vaticle.typedb&lt;/groupId&gt;
    &lt;artifactId&gt;typedb-client&lt;/artifactId&gt;
    <version>{version}</version>
</dependency>
</dependencies>

If you want to depend on snapshot versions of Client Java, by referring to the GitHub commit sha, you can add our snapshot repository to your list of Maven repositories.


<repositories>
    <repository>
        <id>repo.vaticle.com.snapshot</id>
        <name>repo.vaticle.comai</name>
        <url>https://repo.vaticle.com/repository/maven-snapshot/</url>
    </repository>
</repositories>

(Optional) Add logging config

By default, Client Java uses Logback to print errors and debugging info to standard output. As it is quite verbose, use the following steps to set the minimum log level to ERROR:

  1. Create a file in the resources path (src/main/resources by default in a Maven project) named logback.xml.
  2. Copy the following document into the logback.xml:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="ERROR">
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

Resources

Quickstart

First make sure, the TypeDB Server is running.

Import com.vaticle.typedb.client.TypeDB, instantiate a TypeDB Core client and open a session to a database.

package com.vaticle.doc.examples;


import com.vaticle.typedb.client.api.TypeDBClient;
import com.vaticle.typedb.client.api.TypeDBSession;
import com.vaticle.typedb.client.TypeDB;

public class TypeDBQuickstartA {
    public static void main(String[] args) {
        TypeDBClient client = TypeDB.coreClient("localhost:1729");
        // client is open
        TypeDBSession session = client.session("social_network", TypeDBSession.Type.DATA);
        // session is open
        session.close();
        // session is closed
        client.close();
        // client is closed
    }
}

Create transactions to use for reading and writing data.

package com.vaticle.doc.examples;

import com.vaticle.typedb.client.api.TypeDBClient;
import com.vaticle.typedb.client.api.TypeDBSession;
import com.vaticle.typedb.client.api.TypeDBTransaction;
import com.vaticle.typedb.client.TypeDB;

public class TypeDBQuickstartB {
    public static void main(String[] args) {
        TypeDBClient client = TypeDB.coreClient("localhost:1729");

        try (TypeDBSession session = client.session("social_network", TypeDBSession.Type.DATA)) {
            // creating a write transaction
            TypeDBTransaction writeTransaction = session.transaction(TypeDBTransaction.Type.WRITE);
            // write transaction is open
            // write transaction must always be committed (closed)
            writeTransaction.commit();

            // creating a read transaction
            TypeDBTransaction readTransaction = session.transaction(TypeDBTransaction.Type.READ);
            // read transaction is open
            // read transaction must always be closed
            readTransaction.close();
        }

        client.close();
    }
}

Running basic retrieval and insertion queries.

package com.vaticle.doc.examples;


import com.vaticle.typedb.client.api.TypeDBClient;
import com.vaticle.typedb.client.api.TypeDBSession;
import com.vaticle.typedb.client.api.TypeDBTransaction;
import com.vaticle.typedb.client.TypeDB;
import com.vaticle.typeql.lang.TypeQL;

import static com.vaticle.typeql.lang.TypeQL.*;

import com.vaticle.typeql.lang.query.TypeQLMatch;
import com.vaticle.typeql.lang.query.TypeQLInsert;
import com.vaticle.typedb.client.api.answer.ConceptMap;

import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;

public class TypeDBQuickstartC {
    public static void main(String[] args) {
        TypeDBClient client = TypeDB.coreClient("localhost:1729");

        try (TypeDBSession session = client.session("social_network", TypeDBSession.Type.DATA)) {

            try (TypeDBTransaction writeTransaction = session.transaction(TypeDBTransaction.Type.WRITE)) {
                // Insert a person using a WRITE transaction
                TypeQLInsert insertQuery = TypeQL.insert(var("x").isa("person").has("email", "x@email.com"));
                List<ConceptMap> insertedId = writeTransaction.query().insert(insertQuery).collect(Collectors.toList());
                System.out.println("Inserted a person with ID: " + insertedId.get(0).get("x").asThing().getIID());
                // to persist changes, a write transaction must always be committed (closed)
                writeTransaction.commit();
            }

            try (TypeDBTransaction readTransaction = session.transaction(TypeDBTransaction.Type.READ)) {
                // Read the person using a READ only transaction
                TypeQLMatch.Limited getQuery = TypeQL.match(var("p").isa("person")).get("p").limit(10);
                Stream<ConceptMap> answers = readTransaction.query().match(getQuery);
                answers.forEach(answer -> System.out.println(answer.get("p").asThing().getIID()));
            }
        }

        client.close();
    }
}

[Important] Remember that transactions always need to be closed. Committing a write transaction closes it. A read transaction, however, must be explicitly closed by calling the `close()` method on it.

Check out the Concept API to learn about the available methods on the concepts retrieved as the answers to queries.

To view examples of running various TypeQL queries using the Java client, head over to their dedicated documentation pages as listed below.


API Reference

Instantiating a TypeDB Core client

TypeDB.coreClient(String address, int parallelisation);

In order to communicate with TypeDB Core databases via sessions and transactions, we first need to instantiate a TypeDB Core client. The created object connects our application with the running TypeDB Server.

Accepts

Param Description Type Required Default

address

The address (host:port) on which the TypeDB Server is running

String

true

parallelisation

The number of threads to use for server communication

int

false

Scales based on host machine’s number of available CPU cores

Returns

Instantiating a TypeDB Cluster client

TypeDB.clusterClient(Set addresses, TypeDBCredential credential, int parallelisation);

In order to communicate with TypeDB Cluster databases via sessions and transactions, we first need to instantiate a TypeDB Cluster client. The created object connects our application with the running TypeDB Cluster. Please note that Node.js and Python clients always have TLS enabled, and therefore can only connect to a server that is setup with TLS. When instantiating a TypeDB Cluster client, it is sufficient to supply the address of just one server, as the addresses of the other servers will be relayed back to the client. However, to avoid failure in the unlikely event that the single server whose address is provided fails before communicating the addresses of the others, it is best practice to supply addresses of all the servers.

Accepts

Param Description Type Required Default

addresses

Addresses (host:port) on which TypeDB Cluster nodes are running

Set of String

true

credential

User credential and TLS encryption setting

TypeDBCredential

true

parallelisation

The number of threads to use for server communication

int

false

Scales based on host machine’s number of available CPU cores

Returns

Client

Create a session for a database

client.session(String database, Session.Type sessionType, TypeDBOptions options);

Opens a communication tunnel (session) to the given database on the running TypeDB server.

Accepts

Param Description Type Required Default

database

The name of the database with which the session connects.

String

true

N/A

type

The type of session to be created (DATA or SCHEMA)

SessionType

true

N/A

options

Options for the session.

TypeDBOptions

false

N/A

Returns

Retrieve all databases

client.databases().all();

Retrieves all databases running on the TypeDB server.

Returns

List

Check if a database exists

client.databases().contains(String database);

Checks if a database with the given name exists

Accepts

Param Description Type Required Default

database

The database name to be checked.

String

true

N/A

Create a database

client.databases().create(String database);

Create a database with the given name.

Accepts

Param Description Type Required Default

database

The name of the database to be created.

String

true

N/A

Returns

void

Retrieve a database

client.databases().get(String database);

Retrieve a database with the given name.

Accepts

Param Description Type Required Default

database

The name of the database to retrieve.

String

true

N/A

Returns

Database

Delete a database

client.databases().get(String database).delete();

Deletes a database with the given name.

Accepts

Param Description Type Required Default

database

The name of the database to be deleted.

String

true

N/A

Returns

void

Retrieve all users

client.users().all();

Retrieves all users running on the TypeDB server.

Returns

List

Check if a user exists

client.users().contains(String user);

Checks if a user with the given name exists

Accepts

Param Description Type Required Default

user

The user name to be checked.

String

true

N/A

Create a user

client.users().create(String user);

Create a user with the given name.

Accepts

Param Description Type Required Default

user

The name of the user to be created.

String

true

N/A

Returns

void

Retrieve a user

client.users().get(String user);

Retrieve a user with the given name.

Accepts

Param Description Type Required Default

user

The name of the user to retrieve.

String

true

N/A

Returns

user

Delete a user

client.users().delete(String username);

Deletes a user with the given name.

Accepts

Param Description Type Required Default

user

The name of the user to be deleted.

String

true

N/A

Returns

void

Set a user's password

client.users().passwordSet(String username, String password);

Deletes a user with the given name.

Accepts

Param Description Type Required Default

user

The name of the user to update the password of.

String

true

N/A

password

User’s new password.

String

true

N/A

Returns

void

Close a client

client.close();

Closes the client. Before instantiating a new client, the client that’s currently open should first be closed.

Returns

void

Session

Open a transaction

session.transaction(Transaction.Type transactionType, TypeDBOptions options);

Opens a transaction to perform read or write queries on the database connected to the session.

Accepts

Param Description Type Required Default

transactionType

The type of transaction to be created (READ or WRITE).

Transaction.Type

true

options

Options for the session.

TypeDBOptions

false

N/A

Returns

Check if a session is open

session.isOpen();

Checks whether a session is presently open.

Returns

boolean

Check the session's type

session.type();

Checks the current session’s type (SCHEMA or DATA)

Returns

Session.Type

Check the session's database

session.database();

Returns a string indicating what database the session is operating over.

Returns

String

Close a session

session.close();

Closes the session. Before opening a new session, the session currently open should first be closed.

Returns

void

Options

The transaction query options object TypeDBOptions can be used to override the default server behaviour query processing. Use TypeDBOptions.core() to create a new TypeDB Core options object, or TypeDBOptions.cluster() for TypeDB Cluster.

The options are:

  • infer: whether to enable inference for the provided query (only settable at transaction level and above, and only affects read transactions) (default: false)
  • explain: whether to enable explanations for the provided query (only affects read transactions) (default: false)
  • parallel: whether the server should use parallel or single-threaded execution (default: true)
  • prefetchSize: a guideline number of answers that the server should send before the client issues a fresh request (default: 50)
  • traceInference: if enabled, outputs reasoning tracing graphs in the logging directory. Should be used with parallel = false. (default: false)
  • prefetch: if enabled, the first batch of answers is streamed to the client even without an explicit request for it (default: true if query type is match, otherwise false)
  • sessionIdleTimeoutMillis: this timeout allows the server to close sessions if a client terminates or becomes unresponsive (default: 30_000)
  • transactionTimeoutMillis: this timeout will automatically kill transactions, preventing memory leaks in unclosed transactions (default: 300_000)
  • schemaLockAcquireTimeoutMillis: how long the client should wait if opening a session or transaction is blocked by a schema write lock (default: 10_000)

TypeDBClusterOptions has an additional option:

  • readAnyReplica: enables reading data from any replica, potentially boosting read throughput (default: false)

Explicitly enable or disable inference

options.setInfer(boolean enabled)

Override the server defaults to enable or disable inference for the provided query (only settable at transaction level and above, and only affects read transactions)

Accepts

Param Description Type Required Default

enabled

explicitly set inference on or off for this query

boolean

true

Returns

Explicitly enable or disable explanations

options.setExplain(boolean enabled)

Override the server defaults to enable or disable explanation availability for the provided query (only affects read transactions)

Accepts

Param Description Type Required Default

enabled

explicitly set explanations on or off for this query

boolean

true

Returns

Force the server parallelism

options.setParallel(boolean parallel)

Override the server defaults to use parallel or single-threaded query execution

Accepts

Param Description Type Required Default

parallel

use parallel or single-threaded query execution

boolean

true

Returns

Explicitly set query prefetch to a certain size

options.setPrefetchSize(int size)

Override the server defaults for answer batch streaming. This tells the server to pre-compute and stream this number of answers at a time. These are buffered in the client until read. A larger batch size causes the server to compute more answers at a time, blocking the transaction until the batch is computed.

Accepts

Param Description Type Required Default

size

int

true

Returns

Trace and log reasoning inference

options.setTraceInference(boolean traceInference)

Create reasoning traces as graphs logged in the logging directory. Should be used with parallel = false

Accepts

Param Description Type Required Default

traceInference

trace reasoning execution as graphs in log directory

boolean

true

Returns

Explicitly enable or disable prefetch

options.setPrefetch(boolean prefetch)

If enabled, the first batch of answers is streamed to the client even without an explicit request for it

Accepts

Param Description Type Required Default

prefetch

if set to true, the first batch of answers is streamed to the client even without an explicit request for it

boolean

true

Returns

Override default session idle timeout

options.setSessionIdleTimeoutMillis(int timeout)

This timeout allows the server to close sessions if a client terminates or becomes unresponsive

Accepts

Param Description Type Required Default

timeout

int

true

Returns

Override default transaction timeout

options.setTransactionTimeoutMillis(int timeout)

This timeout automatically closes transactions that exceed the configured time. This prevents memory leaks caused by transactions accidentally left unclosed, and kills unresponsive transactions.

Accepts

Param Description Type Required Default

timeout

int

true

Returns

Override default schema lock acquire timeout

options.setSchemaLockAcquireTimeoutMillis(int timeout)

This timeout allows the server to close sessions if a client terminates or becomes unresponsive

Accepts

Param Description Type Required Default

timeout

int

true

Returns

Enable reading data from any replica

clusterOptions.setReadAnyReplica(bool readAnyReplica)

Used to enable reading data from any replica, potentially boosting read throughput

Accepts

Param Description Type Required Default

readAnyReplica

boolean

true

Returns

Transaction

Check the transaction's type

transaction.type();

Checks the transaction’s type (READ or WRITE)

Returns

Transaction.Type

Check if the transaction is open

transaction.isOpen();

Returns

boolean

Access Concept API methods

transaction.concepts();

Gets the ConceptManager for this Transaction, providing access to all Concept API methods.

Returns

Access Concept API - Logic methods

transaction.logic();

Gets the LogicManager for this Transaction, providing access to all Concept API - Logic methods.

Returns

Access Query API methods

transaction.query();

Gets the QueryManager for this Transaction, from which any TypeQL query can be executed.

Returns

Commit a write transaction

transaction.commit();

Commits the changes made via this transaction to the TypeDB database. Whether or not the transaction is commited successfully, it gets closed after the commit call.

Returns

void

Rollback a write transaction

transaction.rollback();

Rolls back the uncommitted changes made via this transaction.

Returns

void

Close a read transaction

transaction.close();

Closes the transaction.

Returns

void

TypeQL

TypeQL, the query language for TypeDB, is written in Java and its API can be used to programmatically construct TypeQL queries.

To use TypeQL, we first add it as a dependency to our pom.xml.

<repositories>
    <repository>
        <id>repo.vaticle.com</id>
        <url>https://repo.vaticle.com/repository/maven/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>com.vaticle.typeql</groupId>
        <artifactId>typeql-lang</artifactId>
        <version>{version}</version>
    </dependency>
</dependencies>

The latest version of typeql-lang can be found in the public Maven repository.

The we import TypeQL.

import com.vaticle.typeql.lang.TypeQL;

We are now ready to construct TypeQL queries, using the methods available on the TypeQL class. Check out the following pages to learn, by example, how the TypeQL API allows construction of various TypeQL queries:

QueryManager

Execute a TypeQL Match query

transaction.query().match(TypeQLMatch query, TypeDBOptions options);

Performs a TypeQL Match query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Match query to be executed.

TypeQLMatch

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Stream<ConceptMap>

Execute a TypeQL Match Aggregate query

transaction.query().match(TypeQLMatch.Aggregate query, TypeDBOptions options);

Performs a TypeQL Match Aggregate query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Match Aggregate query to be executed.

TypeQLMatch.Aggregate

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Execute a TypeQL Match Group query

transaction.query().match(TypeQLMatch.Group query, TypeDBOptions options);

Performs a TypeQL Match Group query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Match Group query to be executed.

TypeQLMatch.Group

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Stream<ConceptMapGroup>

Execute a TypeQL Match Group Aggregate query

transaction.query().match(TypeQLMatch.Group.Aggregate query, TypeDBOptions options);

Performs a TypeQL Match Group Aggregate query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Match Group Aggregate query to be executed.

TypeQLMatch.Group.Aggregate

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Stream<NumericGroup>

Execute a TypeQL Insert query

transaction.query().insert(TypeQLInsert query, TypeDBOptions options);

Performs a TypeQL Insert query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Insert query to be executed.

TypeQLInsert

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Stream<ConceptMap>

Execute a TypeQL Delete query

transaction.query().delete(TypeQLDelete query, TypeDBOptions options);

Performs a TypeQL Delete query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Delete query to be executed.

TypeQLDelete

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Execute a TypeQL Update query

transaction.query().update(TypeQLUpdate query, TypeDBOptions options);

Performs a TypeQL Update query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Update query to be executed.

TypeQLUpdate

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Stream<ConceptMap>

Execute a TypeQL Explain query

transaction.query().explain(ConceptMap.Explainable explainable, TypeDBOptions options);

Performs a TypeQL Explain query in the transaction.

Accepts

Param Description Type Required Default

explainable

The Explainable to be explained.

ConceptMap.Explainable

true

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Stream<Explanation>

Execute a TypeQL Define query

transaction.query().define(TypeQLDefine query, TypeDBOptions options);

Performs a TypeQL Define query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Define query to be executed.

TypeQLDefine

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Execute a TypeQL Undefine query

transaction.query().undefine(TypeQLUndefine query, TypeDBOptions options);

Performs a TypeQL Undefine query in the transaction.

Accepts

Param Description Type Required Default

query

The TypeQL Undefine query to be executed.

TypeQLUndefine

true

N/A

options

Specify query options

TypeDBOptions

false

default TypeDBOptions - uses server defaults

Returns

Answer

The type of answers returned by execution of a query depends on the type of query executed. The table below illustrates the answer types mapped to query types.

Query Type Answer Type
match

Stream/Iterator of ConceptMap

match aggregate (count/min/max/sum/mean/std)

QueryFuture of Numeric

match group

Stream/Iterator of ConceptMapGroup

match group aggregate

Stream/Iterator of NumericGroup

insert

Stream/Iterator of ConceptMap

delete

QueryFuture

update

Stream/Iterator of ConceptMap

explain

Stream/Iterator of Explanation

define

QueryFuture

undefine

QueryFuture

ConceptMap

Retrieve a mapping of variables to concepts

conceptMap.map();

Produces a Map where keys are variable names and values are concepts.

Returns

Map<String, Concept>

Retrieve concepts

conceptMap.concepts();

Return a collection of all the concepts in this ConceptMap.

Returns

Collection

Retrieve a concept corresponding to a specific variable

conceptMap.get(String var)

Retrieve a concept for a given variable name

Accepts

Param Description Type Required Default

var

The string representation of a variable

String

Returns

Retrieve explainable concepts

conceptMap.explainables()

Gets the Explainables object for this ConceptMap, exposing which of the Concepts in this ConceptMap are explainable

Returns

Numeric

Retrieve numeric value of an aggregate answer as a long

numeric.asLong();

Returns

long

Retrieve numeric value of an aggregate answer as a double

numeric.asDouble();

Returns

double

Retrieve numeric value of an aggregate answer

numeric.asNumber();

Returns

Number

Checks if the type of an aggregate answer is a long

numeric.isLong();

Returns

boolean

Checks if the type of an aggregate answer is a double

numeric.isDouble();

Returns

boolean

Checks if the type of an aggregate answer is not a number

conceptMapGroup.isNaN();

Returns

boolean

ConceptMapGroup

Retrieve the concept that is the group owner

conceptMapGroup.owner();

Returns

Retrieve the ConceptMaps of the group

conceptMapGroup.conceptMaps();

Returns

List<ConceptMap>

NumericGroup

Retrieve the concept that is the group owner

numericGroup.owner();

Returns

Retrieve the Numeric answer of the group

numericGroup.numeric();

Returns

Explainables

Retrieve explainable relation

conceptMap.explainables().relation(String variable);

Retrieves the explainable relation with the given variable name.

Accepts

Param Description Type Required Default

variable

The string representation of a variable

String

Returns

Retrieve explainable attribute

conceptMap.explainables().attribute(String variable);

Retrieves the explainable attribute with the given variable name.

Accepts

Param Description Type Required Default

variable

The string representation of a variable

String

Returns

Retrieve explainable ownership

conceptMap.explainables().ownership(String ownerVar, String attributeVar);

Retrieves the explainable attribute ownership with the pair of (owner, attribute) variable names.

Accepts

Param Description Type Required Default

variable

The string representation of a variable

String

Returns

Retrieve explainable relations

conceptMap.explainables().relations();

Retrieves all of this ConceptMap’s explainable relations.

Returns

Map<String, ConceptMap.Explainable>

Retrieve explainable attributes

conceptMap.explainables().attributes();

Retrieves all of this ConceptMap’s explainable attributes.

Returns

Map<String, ConceptMap.Explainable>

Retrieve explainable ownerships

conceptMap.explainables().ownerships();

Retrieves all of this ConceptMap’s explainable attribute ownerships.

Returns

Map<Pair<String, String>, ConceptMap.Explainable>

Explainable

Retrieve conjunction

explainable.conjunction()

Retrieves the subquery of the original query that is actually being explained.

Returns

String

Retrieve ID

explainable.id()

Retrieves the unique ID that identifies this Explainable.

Returns

long

Explanation

Retrieve the rule

explanation.rule();

Retrieves the Rule for this Explanation.

Returns

Rule

Retrieve the conclusion

explanation.conclusion()

Retrieves the Conclusion for this Explanation.

Returns

ConceptMap

Retrieve the condition

explanation.condition()

Retrieves the Condition for this Explanation.

Returns

ConceptMap

Retrieve the variable mapping

explanation.variableMapping()

Retrieves the mapping between rule variables and query variables for this Explanation.

Returns

Map<String, Set>

QueryFuture

Transaction queries that return single answers or empty responses are executed asynchronously on the server. To wait for a query to finish execution, and return its result if there is one, use the ‘get()’ function.

Get the query result

future.get()

Waits for the query to finish execution, and returns its result, if present.

Returns

Returns according to type of query executed

Map the query result

future.map(function)

Transforms the QueryFuture into a new QueryFuture by running the supplied function on the query result when it is returned.

Returns

Return type of supplied function

Version Compatibility

Client Java TypeDB TypeDB Cluster
2.16.1 2.16.1 2.16.1
2.14.1 to 2.14.3 2.14.1 to 2.15.0 2.14.1 to 2.15.0
2.12.0 2.12.0 to 2.13.0 2.13.0
2.9.0 to 2.11.1 2.9.0 to 2.11.1 2.9.0 to 2.11.2
2.8.0 2.8.0 N/A
2.6.0 to 2.6.2 2.6.0 to 2.7.1 N/A
2.5.0 2.1.2 to 2.5.0 2.5.0
2.1.0 to 2.4.0 2.1.2 to 2.5.0 2.1.2 to 2.3.0
2.0.1 2.0.2 2.0.2
2.0.0 2.0.0, 2.0.1 2.0.0, 2.0.1
1.8.3 1.8.0 to 1.8.4 N/A
1.8.2 1.8.0, 1.8.1 N/A
1.8.0 to 1.8.1 1.8.0 N/A