The Polypheny C++ driver provides seamless access to Polypheny’s diverse data models, including relational, graph, and document models. Unlike traditional JDBC drivers, the C++ driver is tailored specifically for Polypheny, eliminating the need for connection unwrapping. This documentation provides examples for executing queries in various data models using the C++ driver.
Supported Data Models and Query Languages
The Polypheny C++ driver supports multiple data models and query languages. Some examples of possible combinations are shown in the table below. The languageName
parameter is used to specify the language a statement is written in on execution.
Data Model | Query Language | languageName Parameter |
---|---|---|
Relational | SQL | sql |
Document | MongoDB Query Language | mongo |
Labeled Property Graph | Cypher | cypher |
Executing an SQL Statement
The following code snippet demonstrates how to execute a simple SQL query to retrieve values from the rows from the emp
table. The example further shows how to interact with the metadata provided together with the result set. The metadata describes the rows of the result.
std::string host = "localhost";
std::string username = "pa";
std::string password = "";
// establish connection
Connection::Connection database_connection = Connection::Connection(host, username, password);
// create a cursor
Connection::Cursor cursor(database_connection);
// execute a statement in the language SQL on the namespace public
std::unique_ptr<Results::Result> result = cursor.execute("sql", "SELECT * FROM emp;", "public");
// check the datamodel of the returned result
if (result->get_result_type() != Results::ResultType::RELATIONAL) {
throw std::runtime_error("Received result is of unexpected type");
}
// unwrap the result to one in the specific datamodel to unlock model specific operations
auto* relational_result = result->unwrap<Results::RelationalResult>();
// example on interacting with metadata
auto metadata = relational_result->get_metadata();
uint32_t columns_count = metadata->get_column_count();
std::vector<std::string> column_labels(columns_count);
for (uint32_t i = 0; i < columns_count; ++i) {
column_labels[i] = metadata->get_column_meta(i).get_column_label();
}
// iterate over the rows of the result
std::vector<std::vector<std::string>> rows;
for (const auto& row : *relational_result) {
// value in rows can be accessed using indexes, column names or iterators
std::string first_name = row[0].as_string();
std::string last_name = row["last_name"].as_string();
double salary = row.at("salary").as_double();
bool part_of_c_suite = row.at(3).as_boolean()
// process each vale of a row
for (const auto& value : row) {
std::cout << value.as_string() << std::endl;
}
}
Executing a MongoDB Query Language (MQL) Query
Below is an example of executing a MongoDB Query Language (MQL) query to retrieve all documents from the emp
collection and accessing all their key-value pairs.
std::string host = "localhost";
std::string username = "pa";
std::string password = "";
// establish connection
Connection::Connection database_connection(host, username, password);
// create a cursor
Connection::Cursor cursor(database_connection);
// execute a statement in the langage MQL on the namespace public
std::unique_ptr<Results::Result> result = cursor.execute("mongo", "db.emp.find()", "public");
// check the datamodel of the returned result
if (result->get_result_type() != Results::ResultType::DOCUMENT) {
throw std::runtime_error("Received result is of unexpected type");
}
// unwrap the result to one in the specific datamodel to unlock model specific operations
auto* document_result = result->unwrap<Results::DocumentResult>();
// iterate over all documents returned by the query
for (const auto &document : *document_result) {
// value in documents can be accessed using the string keys or iterators
std::string first_name = document["first_name"].as_string();
double salary = document.at("salary").as_double()
// process each key-value pair in the document
for (const auto &entry : document) {
std::cout << entry.first << ": " << entry.second << std::endl;
}
}
Executing a Cypher Query (Graph)
The following example demonstrates how to execute a Cypher query to retrieve all nodes labeled as customers
.
std::string host = "localhost";
std::string username = "pa";
std::string password = "";
// establish connection
Connection::Connection database_connection(host, username, password);
// create a cursor
Connection::Cursor cursor(database_connection);
// execute a statement in the langage Cypher on the namespace public
std::unique_ptr<Results::Result> result = cursor.execute(
"cypher",
"MATCH (c:customers) RETURN c",
"public"
);
// check the datamodel of the returned result
if (result->get_result_type() != Results::ResultType::GRAPH) {
throw std::runtime_error("Received result is of unexpected type");
}
// unwrap the result to one in the specific datamodel to unlock model specific operations
auto* graph_result = result->unwrap<Results::GraphResult>();
// iterate over all nodes returned by the query
for (const auto &graph_element : *graph_result) {
// properties in nodes/edges can be accessed using the string keys or iterators
std::string first_name = graph_element["first_name"].as_string();
int32_t bonus_points = graph_element.at("bonus_points").as_int32_t();
// process each property of the node/edge
for (const auto &property : *graph_element) {
std::cout << property.first << ": " << property.second << std::endl;
}
}
Result Processing
Each query execution returns a Result
object, which must be unwrapped to the appropriate result type, such as DocumentResult
, RelationalResult
, GraphResult
or ScalarResult
. The result type depends on the query and is not a user’s choice.
To determine the type of result, the get_result_type
method can be used. It is crucial to unwrap the result to the correct type. An exception is thrown otherwise.