Connecting to Polypheny from C++ applications is straightforward and efficient, especially when using the Polypheny C++ Driver. This driver offers robust performance and access to the full range of Polypheny features via the Prism query interface.
While other connection options exist, such as the REST interface and HTTP interface, the C++ driver is the recommended method for C++ applications due to its performance and feature completeness. Examples and guidance for using the REST interface can be found in the REST query interface documentation.
Prerequisites
The Polypheny C++ Driver connects to the Prism Query Interface, which is deployed with every Polypheny instance by default. However, if you run into problems, ensure that the interface is correctly deployed. You can check the currently deployed interfaces in the Polypheny user interface under “Interfaces.”
Installation
To use the Polypheny C++ driver, you need to have the driver installed and configured. You can download the driver from Polypheny’s C++ Driver Releases and follow the installation instructions specific to your operating system.
Usage
Integrating the Polypheny C++ Driver into your application involves several key steps:
- Establish a connection to your Polypheny database:
std::string host = "localhost"; std::string username = "pa"; std::string password = ""; // Establish connection Connection::Connection database_connection(host, username, password);
- Create a cursor object to execute SQL queries:
// Create a cursor Connection::Cursor cursor(database_connection);
- Execute the query:
// Execute a statement in the language SQL on the namespace public std::unique_ptr<Results::Result> result = cursor.execute("sql", "SELECT * FROM emp;", "public");
- Process the result of the query:
if (result->get_result_type() != Results::ResultType::RELATIONAL) { throw std::runtime_error("Received result is of unexpected type"); } auto* relational_result = result->unwrap<Results::RelationalResult>(); for (const auto& row : *relational_result) { std::string first_name = row[0].as_string(); std::string last_name = row["last_name"].as_string(); double salary = row.at("salary").as_double(); std::cout << "First Name: " << first_name << ", Last Name: " << last_name << ", Salary: " << salary << std::endl; }
- Properly close connections and other resources to prevent leaks: The C++ driver automatically handles the resource cleanup, ensuring efficient memory management. However, ensure that all connections and resources are correctly managed within your application.
Example 1 - SQL
Here’s a basic example for establishing a connection and executing a simple SQL query:
#include "PolyphenyCPPDriver.h"
#include <iostream>
#include <memory>
#include <string>
int main() {
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 language SQL on the namespace public
std::unique_ptr<Results::Result> result = cursor.execute("sql", "SELECT * FROM emp;", "public");
// Check the data model 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 data model to unlock model-specific operations
auto* relational_result = result->unwrap<Results::RelationalResult>();
// Iterate over the rows of the result
for (const auto& row : *relational_result) {
std::string first_name = row[0].as_string();
std::string last_name = row["last_name"].as_string();
double salary = row.at("salary").as_double();
std::cout << "First Name: " << first_name << ", Last Name: " << last_name << ", Salary: " << salary << std::endl;
}
return 0;
}
Example 2 - MongoDB Query Language (MQL)
The following example demonstrates how to execute a MongoDB Query Language (MQL) query to retrieve all documents from the emp
collection and access their key-value pairs:
#include "PolyphenyCPPDriver.h"
#include <iostream>
#include <memory>
#include <string>
int main() {
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 language MQL on the namespace public
std::unique_ptr<Results::Result> result = cursor.execute("mongo", "db.emp.find()", "public");
// Check the data model 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 data model 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) {
std::string first_name = document["first_name"].as_string();
double salary = document.at("salary").as_double();
std::cout << "First Name: " << first_name << ", Salary: " << salary << std::endl;
// Process each key-value pair in the document
for (const auto& entry : document) {
std::cout << entry.first << ": " << entry.second << std::endl;
}
}
return 0;
}
Example 3 - Cypher Query (Graph)
The following example demonstrates how to execute a Cypher query to retrieve all nodes labeled as customers
:
#include "PolyphenyCPPDriver.h"
#include <iostream>
#include <memory>
#include <string>
int main() {
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 language Cypher on the namespace public
std::unique_ptr<Results::Result> result = cursor.execute(
"cypher",
"MATCH (c:customers) RETURN c",
"public"
);
// Check the data model 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 data model 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) {
std::string first_name = graph_element["first_name"].as_string();
int32_t bonus_points = graph_element.at("bonus_points").as_int32_t();
std::cout << "First Name: " << first_name << ", Bonus Points: " << bonus_points << std::endl;
// Process each property of the node/edge
for (const auto& property : *graph_element) {
std::cout << property.first << ": " << property.second << std::endl;
}
}
return 0;
}
Example 4 - Metadata
The Polypheny C++ driver also allows you to retrieve metadata from the database. Below is an example of how to retrieve a list of all tables:
#include "PolyphenyCPPDriver.h"
#include <iostream>
#include <memory>
#include <string>
int main() {
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 to retrieve metadata
std::unique_ptr<Results::Result> result = cursor.execute("sql", "SHOW TABLES;", "public");
// Check the data model of the returned result
if (result->get_result_type() != Results::ResultType::RELATIONAL) {
throw std::runtime_error("Received result is of unexpected type");
}
auto* relational
_result = result->unwrap<Results::RelationalResult>();
// Iterate over the rows of the result to get table names
std::cout << "Table Names:" << std::endl;
for (const auto& row : *relational_result) {
std::cout << row[0].as_string() << std::endl;
}
return 0;
}
Best Practices
- Connection Management: Ensure that database connections, statements, and result sets are managed and closed properly to avoid resource leaks.
- Error Handling: Implement comprehensive error handling to manage exceptions and ensure your application can recover from or report database access issues effectively.
- Credential Security: Securely manage database credentials, avoiding hard-coded values in source code for production environments.