JDBC Driver - Multimodel Extension

The JDBC standard is inherently oriented towards relational databases and SQL queries. However, Polypheny extends beyond these limitations, supporting multiple data models and languages. To accommodate this, the JDBC standard has been extended in a feature known as the Multimodel Extension which goes beyond what is traditionally available through JDBC.

The features of the Multimodel Extension are considered experimental and are still a work in progress. Nonetheless, high priority is given to its development. Frequent changes and rapid expansion of features thus occur.

Supported Data Models

The Multimodel Extension of the Polypheny JDBC Driver is designed to accommodate a diverse range of data models. Specifically, it supports the Relational model, the Labeled Property Graph model (LPG), and the Document model. This allows Java applications to interact with all data models currently supported by Polypheny using a single driver.

Supported Query Languages

The Polypheny JDBC Driver officially supports the following query languages. While other query languages supported by Polypheny might work as well, they are not tested for compatibility.

Query Language Name used for the languageName parameter
SQL sql
MongoDB Query Language mql
Cypher cypher

When using the execute method, the languageName parameter needs to be set to one of these strings.

Unwrapping for Multi-Model Support

To access the features of the Multimodel Extension, the JDBC Connection object must be unwrapped to a PolyConnection object, which provides Polypheny-specific features. Specifically, you can use the createPolyStatement method to generate a statement object aligned with the Multimodel Extension.

For detailed documentation on the PolyStatement object, please refer to the corresponding documentation.

Usage:

try (
    Connection connection = DriverManager.getConnection("jdbc:polypheny://localhost:20590");
) {
    if (connection.isWrapperFor(PolyConnection.class)) {
        PolyConnection polyConnection = connection.unwrap(PolyConnection.class);
        PolyStatement polyStatement = polyConnection.createPolyStatement();

        // You can now use polyStatement to execute multi-model queries...
    }
} catch (SQLException e) {
    e.printStackTrace();
}

Executing an MQL Query

The PolyStatement yielded by the unwrapping process above can now be used to execute statements in any of the supported languages. An example for the MongoDB Query Language (MQL) is given below.

For detailed documentation on the PolyStatement object, please refer to the corresponding documentation.

Imagine a collection of documents, each storing information about a specific person. To retrieve all people in our database and print them to System.out, we can use the code below.

DocumentResult result = polyStatement.execute("mongotest", "mongo", "db.people.find({})").unwrap(DocumentResult.class);
Iterator<PolyDocument> documents = result.iterator();

while (documents.hasNext()) {
    PolyDocument document = documents.next();
    System.out.println("ID: " + document.get("_id").asInt());
    System.out.println("Name: " + document.get("name").asString());
}

Executing an SQL Statement

The PolyStatement yielded by the unwrapping process can now be used to execute statements in any of the supported languages. An example for SQL is given below.

For detailed documentation on the PolyStatement object, please refer to the corresponding documentation.

Imagine a collection of documents, each storing information about a specific person. To retrieve all people in our database and print them to System.out, we can use the code below.

RelationalResult result = polyStatement.execute("sqltest", "sql", "SELECT * FROM people").unwrap(RelationalResult.class);
Iterator<PolyRow> rows = result.iterator();

while (rows.hasNext()) {
    PolyRow row = rows.next();
    System.out.println("ID: " + row.get("id").asInt());
    System.out.println("Name: " + row.get("name").asString());
}

Executing a Cypher Query

The PolyStatement yielded by the unwrapping process can now be used to execute statements in any of the supported languages. An example for Cypher (for the Graph data model) is given below.

For detailed documentation on the PolyStatement object, please refer to the corresponding documentation.

Imagine a graph containing nodes representing people. To retrieve all nodes labeled as Person and print their names, we can use the code below:

GraphResult result = polyStatement.execute("cyphertest", "cypher", "MATCH (n:Person) RETURN n ORDER BY n.id").unwrap(GraphResult.class);
Iterator<PolyGraphElement> elements = result.iterator();

while (elements.hasNext()) {
    PolyGraphElement element = elements.next();
    System.out.println("Name: " + element.get("name").asString());
    System.out.println("Labels: " + element.getLabels());
}

Executing a Cypher Query Returning a Relational Result

It is possible for queries in the Labeled Property Graph model (LPG) to return a relational result. Their handling and processing is identical to the results of the relational model. Below, an example of such a statement in LPG and the handling of its result is given:

Imagine a graph containing nodes representing people. To retrieve the name and ID of a person named Alice, we can use the code below:

RelationalResult result = polyStatement.execute("cyphertest", "cypher", "MATCH (n:Person {name: 'Alice'}) RETURN n.name, n.id").unwrap(RelationalResult.class);
Iterator<PolyRow> rows = result.iterator();

while (rows.hasNext()) {
    PolyRow row = rows.next();
    System.out.println("Name: " + row.get("n.name").asString());
    System.out.println("ID: " + row.get("n.id").asString());
}

Unwrapping Result Types

As shown in the examples above. The result returned by the execute method is then unwrapped into one of the concrete result types RelationalResult, DocumentResult, GraphResult or ScalarResult. The type to unwrap to must match the type of result returned by the query and is not of the users’ choice. Trying to unwrap to a different result type will cause an exception to be thrown.

To determine the type of result, the method getResultType provided by the result object can be used.

© Polypheny GmbH. All Rights Reserved.