Wrapper around ScyllaDB's Rust Driver, which is API-compatible with both ScyllaDB and Datastax C/C++ Driver and may be considered a drop-in replacement (with some minor limitations, see Limitations).
In this section we will go over most important CMake options and what each of them controls.
CASS_BUILD_SHARED- Build shared driver library (.so).ONby default.CASS_BUILD_STATIC- Build static driver library (.a).ONby default.CASS_BUILD_INTEGRATION_TESTS- Build integration tests (seeTestingsection below)OFFby default.CASS_BUILD_EXAMPLES- Build examples (seeExamplessection below).OFFby default.CASS_USE_STATIC_LIBS- Link against static libraries when building tests/examples.OFFby default.CMAKE_BUILD_TYPE- Controls the cargo profile library is built with. Possible values are:Debug,RelWithDebInfoandRelease. Default value isDebug. For more information, see the profiles definitions inscylla-rust-wrapper/Cargo.toml.
For example, to build a shared driver library (no static library) in release mode and integration tests you can do:
mkdir build
cd build
cmake -DCASS_BUILD_STATIC=OFF -DCASS_BUILD_INTEGRATION_TESTS=ON -DCMAKE_BUILD_TYPE=Release ..
makeThere are some examples in the examples directory. To run a single example:
cd examples/cloud
gcc cloud.c PATH_TO_CPP_RUST/scylla-rust-wrapper/target/debug/libscylla_cpp_driver.so -Wl,-rpath,PATH_TO_CPP_RUST/build -I PATH_TO_CPP_RUST/include -o cloud
./cloud path_to_connection_bundle username password#include <cassandra.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
/* Setup and connect to cluster */
CassFuture* connect_future = NULL;
CassCluster* cluster = cass_cluster_new();
CassSession* session = cass_session_new();
char* hosts = "127.0.0.1";
if (argc > 1) {
hosts = argv[1];
}
/* Add contact points */
cass_cluster_set_contact_points(cluster, hosts);
/* Provide the cluster object as configuration to connect the session */
connect_future = cass_session_connect(session, cluster);
if (cass_future_error_code(connect_future) == CASS_OK) {
CassFuture* close_future = NULL;
/* Build statement and execute query */
const char* query = "SELECT release_version FROM system.local WHERE key='local'";
CassStatement* statement = cass_statement_new(query, 0);
CassFuture* result_future = cass_session_execute(session, statement);
if (cass_future_error_code(result_future) == CASS_OK) {
/* Retrieve result set and get the first row */
const CassResult* result = cass_future_get_result(result_future);
const CassRow* row = cass_result_first_row(result);
if (row) {
const CassValue* value = cass_row_get_column_by_name(row, "release_version");
const char* release_version;
size_t release_version_length;
cass_value_get_string(value, &release_version, &release_version_length);
printf("release_version: '%.*s'\n", (int)release_version_length, release_version);
}
cass_result_free(result);
} else {
/* Handle error */
const char* message;
size_t message_length;
cass_future_error_message(result_future, &message, &message_length);
fprintf(stderr, "Unable to run query: '%.*s'\n", (int)message_length, message);
}
cass_statement_free(statement);
cass_future_free(result_future);
/* Close the session */
close_future = cass_session_close(session);
cass_future_wait(close_future);
cass_future_free(close_future);
} else {
/* Handle error */
const char* message;
size_t message_length;
cass_future_error_message(connect_future, &message, &message_length);
fprintf(stderr, "Unable to connect: '%.*s'\n", (int)message_length, message);
}
cass_future_free(connect_future);
cass_cluster_free(cluster);
cass_session_free(session);
return 0;
}The logging API and implementation are compatible with the C++ driver, for more details please refer to the logging documentation.
As the tracing framework is used under the hood to instrument the collection of logs from the Rust driver and the scylla-rust-wrapper,
the logging level and callback are passed through a custom event subscriber which is globally set as default when cass_log_set_level is called.
So, cass_log_set_level must be called only once as subsequent attempts trying to modify the globally set event subscriber will be ignored.
Also, Rust programs using CPP RS Driver under the hood must avoid calling tracing::subscriber::set_global_default as this will cause conflicts.
Note: The logging configuration must be done before any other driver function is called, otherwise, the default logging callback will be used, and logs will appear on stderr.
void on_log(const CassLogMessage* message, void* data) {
/* Handle logging */
}
int main() {
void* log_data = NULL /* Custom log resource */;
cass_log_set_callback(on_log, log_data);
cass_log_set_level(CASS_LOG_INFO);
/* Create cluster and connect session */
}The driver inherits almost all the features of C/C++ and Rust drivers, such as:
- Asynchronous API
- Shard-aware routing
- Simple, Prepared and Batch statements
- Query paging
- CQL binary protocol version 4
- Load balancing policies
- Retry policies
- SSL
- Authentication
- Tuples and UDTs
- Nested collections
- Data types
- Schema metadata (keyspace metadata, materialized views, etc.)
This section covers all the functions that were present in old cpp-driver but are not present in this driver, and current status / reasons.
Functions here are simply not (yet) implemented. We may implement them at some point. External contributions for those are welcome.
Index metadata
Issue: #272 Implementation will need support in Rust Driver first. Issue: scylladb/scylla-rust-driver#1034
- cass_index_meta_name
- cass_index_meta_options
- cass_index_meta_target
- cass_index_meta_type
- cass_table_meta_index
- cass_table_meta_index_by_name
- cass_table_meta_index_by_name_n
- cass_table_meta_index_count
- cass_iterator_get_index_meta
- cass_iterator_indexes_from_table_meta
Custom allocator
Function: cass_alloc_set_functions Issue: #277
cass_cluster_set_prepare_on_all_hosts
Issue: #278 Will need Rust Driver support first: scylladb/scylla-rust-driver#1284
cass_session_get_speculative_execution_metrics
Issue: #266 Will need Rust Driver support first: scylladb/scylla-rust-driver#1041
Clustering key order
Issue: #271
- cass_materialized_view_meta_clustering_key_order
- cass_table_meta_clustering_key_order
Schema version
Issue: #270 Rust Driver issue: scylladb/scylla-rust-driver#1307
- cass_schema_meta_snapshot_version
- cass_schema_meta_version
Custom authenticator
Issue: #265
- cass_authenticator_address
- cass_authenticator_class_name
- cass_authenticator_exchange_data
- cass_authenticator_hostname
- cass_authenticator_response
- cass_authenticator_set_error
- cass_authenticator_set_error_n
- cass_authenticator_set_exchange_data
- cass_authenticator_set_response
- cass_cluster_set_authenticator_callbacks
cass_cluster_set_use_hostname_resolution
We need to understand use cases for this, and decide if we want this or not. Issue: #426
Those functions need features that are not supported by ScyllaDB, or are only experimental. We will most likely not work on them (until ScyllaDB supports those features), but we may consider external contributions.
Custom payload
ScyllaDB has basically no support for custom payload. They are only used for Tablets support in drivers: https://github.com/scylladb/scylladb/blob/master/docs/dev/protocol-extensions.md#negotiate-sending-tablets-info-to-the-drivers Issue: #261 Implementation will need support in Rust Driver first. No issue for that yet.
- cass_custom_payload_free
- cass_custom_payload_new
- cass_custom_payload_remove
- cass_custom_payload_remove_n
- cass_custom_payload_set
- cass_custom_payload_set_n
- cass_future_custom_payload_item
- cass_future_custom_payload_item_count
- cass_batch_set_custom_payload
- cass_statement_set_custom_payload
Set keyspace on statement
This requires CQLv5 protocol, not yet supported by ScyllaDB or Rust Driver. Issue: #279 Implementation will need support in Rust Driver first. No issue for that yet.
- cass_batch_set_keyspace
- cass_batch_set_keyspace_n
- cass_statement_set_keyspace
- cass_statement_set_keyspace_n
UDF metadata
UDFs are experimental in ScyllaDB Issue: #275 Implementation will need support in Rust Driver first. Issue: scylladb/scylla-rust-driver#1034
- cass_function_meta_argument
- cass_function_meta_argument_count
- cass_function_meta_argument_type_by_name
- cass_function_meta_argument_type_by_name_n
- cass_function_meta_body
- cass_function_meta_called_on_null_input
- cass_function_meta_full_name
- cass_function_meta_language
- cass_function_meta_name
- cass_function_meta_return_type
- cass_iterator_functions_from_keyspace_meta
- cass_iterator_get_function_meta
- cass_keyspace_meta_function_by_name
- cass_keyspace_meta_function_by_name_n
UDA metadata
UDAs are experimental in ScyllaDB Issue: #273 Implementation will need support in Rust Driver first. Issue: scylladb/scylla-rust-driver#1034
- cass_aggregate_meta_argument_count
- cass_aggregate_meta_argument_type
- cass_aggregate_meta_final_func
- cass_aggregate_meta_full_name
- cass_aggregate_meta_init_cond
- cass_aggregate_meta_name
- cass_aggregate_meta_return_type
- cass_aggregate_meta_state_func
- cass_aggregate_meta_state_type
- cass_iterator_aggregates_from_keyspace_meta
- cass_iterator_get_aggregate_meta
- cass_keyspace_meta_aggregate_by_name
- cass_keyspace_meta_aggregate_by_name_n
Table / Keyspace metadata: is_virtual
Scylla does not have the same system tables that Cassandra exposes this information in. Issue: #268
- cass_keyspace_meta_is_virtual
- cass_table_meta_is_virtual
Functions in this section were intentionally not implemented. They may be incompatible with driver architecture, deprecated / no-op in the old driver, or footguns that make no sense. We do not plan to implement those, unless there is a very good reason to. If you require some of those functionalities, please open an issue, and we'll discuss how we can solve this.
Raw metadata accessors
Those APIs are not really compatible with the driver architecture, implementing it would be difficult. If you need some of it, please open an issue, so that we can learn about your use case and figure out how we can address it.
- cass_keyspace_meta_field_by_name
- cass_keyspace_meta_field_by_name_n
- cass_table_meta_field_by_name
- cass_table_meta_field_by_name_n
- cass_materialized_view_meta_field_by_name
- cass_materialized_view_meta_field_by_name_n
- cass_column_meta_field_by_name
- cass_column_meta_field_by_name_n
- cass_iterator_fields_from_column_meta
- cass_iterator_fields_from_keyspace_meta
- cass_iterator_fields_from_materialized_view_meta
- cass_iterator_fields_from_table_meta
- cass_iterator_get_meta_field_name
- cass_iterator_get_meta_field_value
- cass_function_meta_field_by_name
- cass_function_meta_field_by_name_n
- cass_iterator_fields_from_function_meta
- cass_aggregate_meta_field_by_name
- cass_aggregate_meta_field_by_name_n
- cass_iterator_fields_from_aggregate_meta
- cass_index_meta_field_by_name
- cass_index_meta_field_by_name_n
- cass_iterator_fields_from_index_meta
Meaningless for our driver
Because of different architectures of new and old driver, those configurations can't be directly translated.
- cass_cluster_set_max_reusable_write_objects
- cass_cluster_set_new_request_ratio
- cass_cluster_set_queue_size_io
Footguns, ancient APIs
Those API are simply bad in our opinion, and have good replacements.
- cass_statement_add_key_index: Prepared statements should be used instead
- cass_cluster_set_prepare_on_up_or_add_host: Driver automatically reprepares statements, and events are unreliable.
- cass_cluster_set_no_compact: Ancient feature, we see no point in supporting it.
Tracing
Semantics of those functions are really weird. Old driver fetches tracing data in order to wait until it becomes available, but has no API to expose it to the user, who must fetch the data again. If some users need tracing APIs, we'll prefer to implement new ones that actually expose tracing info.
- cass_cluster_set_tracing_consistency
- cass_cluster_set_tracing_max_wait_time
- cass_cluster_set_tracing_retry_wait_time
"Custom" type
This is deprecated basically everywhere and has no good use, especially with Scylla.
- cass_collection_append_custom
- cass_collection_append_custom_n
- cass_statement_bind_custom
- cass_statement_bind_custom_by_name
- cass_statement_bind_custom_by_name_n
- cass_statement_bind_custom_n
- cass_tuple_set_custom
- cass_tuple_set_custom_n
- cass_user_type_set_custom
- cass_user_type_set_custom_by_name
- cass_user_type_set_custom_by_name_n
- cass_user_type_set_custom_n
Deprecated and no-op in old driver
Those APIs were already deprecated, and not doing anything. We see no reason to keep them.
- cass_cluster_set_max_concurrent_creation
- cass_cluster_set_max_concurrent_requests_threshold
- cass_cluster_set_max_connections_per_host
- cass_cluster_set_max_requests_per_flush
- cass_cluster_set_pending_requests_high_water_mark
- cass_cluster_set_pending_requests_low_water_mark
- cass_cluster_set_queue_size_event
- cass_cluster_set_write_bytes_high_water_mark
- cass_cluster_set_write_bytes_low_water_mark
- cass_log_cleanup
- cass_log_set_queue_size
DSE functions
Our driver doesn't support DSE-exclusive features.
- cass_cluster_set_cloud_secure_connection_bundle
- cass_cluster_set_cloud_secure_connection_bundle_n
- cass_cluster_set_cloud_secure_connection_bundle_no_ssl_lib_init
- cass_cluster_set_cloud_secure_connection_bundle_no_ssl_lib_init_n
- cass_cluster_set_monitor_reporting_interval
Integration tests from the original cpp-driver are compilable but not all tests pass yet.
Some tests are added to GitHub Actions workflows and are used to test every pull request on both ScyllaDB and Cassandra clusters.
To build and run the integration tests several requirements need to be met:
- Install
libuvandopensslon your system:
# On Ubuntu
sudo apt-get install libuv1-dev
sudo apt-get install libssl1.0.0
# On Fedora
sudo dnf install libuv-devel
sudo dnf install openssl-devel- Clone and install scylla-ccm system-wide.
Finally, to build the integration tests:
mkdir build && cd build
cmake -DCASS_BUILD_INTEGRATION_TESTS=ON .. && make
Now, use --gtest_filter to run certain integration tests:
./cassandra-integration-tests --scylla --version=<SCYLLA_VERSION> --category=CASSANDRA --verbose=ccm --gtest_filter="ClusterTests.*"Note: Tests that pass with ScyllaDB and Cassandra clusters can be found in Makefile: SCYLLA_TEST_FILTER and CASSANDRA_TEST_FILTER env variables.
If you want to distribute the driver or install it system-wide, you can create
installable packages rather than copying files manually. Packages bundle the
driver's libraries, headers, and metadata so your operating system's package
manager (like apt, dnf, or the macOS/Windows installer) can install, update,
and remove the driver cleanly.
This project uses CPack, a packaging tool included with CMake, to generate packages for all major platforms.
First, compile the driver in release mode:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config ReleaseFrom the build directory, run cpack with a "generator" flag (-G) that
matches your target system:
Linux has two main package formats:
- DEB (
.deb) — used by Debian, Ubuntu, and derivatives - RPM (
.rpm) — used by Fedora, RHEL, Rocky Linux, CentOS, and derivatives
cd build
cpack -G DEB -C Release # Creates a .deb file
cpack -G RPM -C Release # Creates a .rpm fileYou can then install the resulting package with your package manager:
sudo apt install ./scylla-cpp-driver*.deb # Debian/Ubuntu
sudo dnf install ./scylla-cpp-driver*.rpm # Fedora/RHELmacOS supports two distribution formats:
- productbuild (
.pkg) — standard macOS installer package - DragNDrop (
.dmg) — disk image that users drag to Applications
cd build
cpack -G productbuild -C Release # Creates a .pkg installer
cpack -G DragNDrop -C Release # Creates a .dmg disk imageWindows uses MSI installers, generated via the WiX Toolset (version 3.11 or later).
Installing WiX Toolset:
-
Via Chocolatey (recommended):
choco install wixtoolset
-
Manual download: Get the installer from WiX Toolset releases and run the
.exeinstaller. Make sure to add WiX to your PATH during installation.
Creating the package:
cd build
cpack -G WIX -C ReleaseThe installer places files in Program Files\ScyllaDB\Scylla CPP Driver.
GitHub Actions automatically builds packages on every release. See:
.github/workflows/build-cpack-packages.yml— builds packages for all platforms.github/workflows/release-upload-packages.yml— attaches packages to GitHub releases
- Slack: http://slack.scylladb.com/
Issuessection of GitHub repository
- CQL binary protocol version 4
This project is licensed under the GNU Lesser General Public License v2.1