A ScyllaDB database driver for the Rust sqlx framework.
This crate adapts the scylla-rust-driver to the sqlx interface, allowing sqlx queries, connection pools, migrations, tests, and type conversions to be used with ScyllaDB.
sqlx provides testing and migration features that are useful when working with a database-backed application.
Using those features through this driver avoids having to maintain separate testing and migration infrastructure.
use sqlx_scylladb::ScyllaDBPoolOptions;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let pool = ScyllaDBPoolOptions::new()
.max_connections(5)
.connect("scylladb://localhost/test")
.await?;
sqlx::query("INSERT INTO users(id, name) VALUES(?, ?)")
.bind(1)
.bind("Alice")
.execute(&pool)
.await?;
let (name,): (String,) = sqlx::query_as("SELECT name FROM users WHERE id = ?")
.bind(1)
.fetch_one(&pool)
.await?;
assert_eq!("Alice", name);
Ok(())
}The driver reads the connection URL from DATABASE_URL and also supports SCYLLADB_URL.
scylladb://myname:mypassword@localhost:9042/my_keyspace?nodes=example.test,example2.test:9043&tcp_nodelay&tcp_keepalive=40&compression=lz4&replication_strategy=simple&replication_factor=2&page_size=10| Part | Required | Example | Explanation |
|---|---|---|---|
| scheme | Required | scylladb | Must be scylladb. |
| username | Optional | myname | Specify the username for user authentication. |
| password | Optional | mypassword | Specify the password for user authentication. |
| host | Required | localhost | The hostname of the initial node to contact. |
| port | Optional | 9042 | Specify the port number. The default is 9042. |
| path | Required | my_keyspace | Specify the keyspace. |
| Name | Example | Explanation |
|---|---|---|
| nodes | example.test,example2.test:9043 | Additional nodes to contact, separated by commas. |
| tcp_nodelay | Enables TCP_NODELAY. This is a key-only option and does not require a value. | |
| tcp_keepalive | 40 | TCP keepalive interval, in seconds. |
| compression | lz4 | Compression for protocol traffic. Supported values are lz4 and snappy. |
| replication_strategy | SimpleStrategy | Replication strategy used when the migration support creates a keyspace. Supported values are simple, network_topology, SimpleStrategy, and NetworkTopologyStrategy. |
| replication_factor | 2 | Replication factor used when the migration support creates a keyspace. |
| page_size | 10 | Maximum number of rows requested in each page of a paged query. |
| tls_rootcert | /etc/certs/ca.crt | Path to the root CA certificate used for TLS server verification. |
| tls_cert | /etc/certs/client.crt | Path to the client certificate used for TLS client authentication. |
| tls_key | /etc/certs/client.key | Path to the private key corresponding to tls_cert. |
Basic type bindings.
- ASCII (&str, String, Box<str>, Cow<'_, str>, Rc<str>, Arc<str>)
- TEXT (&str, String, Box<str>, Cow<'_, str>, Rc<str>, Arc<str>)
- BOOLEAN (bool)
- TINYINT (i8)
- SMALLINT (i16)
- INT (i32)
- BIGINT (i64)
- FLOAT (f32)
- DOUBLE (f64)
- BLOB (Vec<u8>)
- UUID (uuid::Uuid)
- TIMEUUID (scylla::value::CqlTimeuuid)
- TIMESTAMP (scylla::value::CqlTimestamp, chrono::DateTime<Utc>, time::OffsetDateTime)
- DATE (scylla::value::CqlDate, chrono::NaiveDate, time::Date)
- TIME (scylla::value::CqlTime, chrono::NaiveTime, time::Time)
- INET (std::net::IpAddr)
- DECIMAL (bigdecimal::Decimal)
- Counter (deserialize only) (scylla::value::Counter)
- Duration
- Varint
List or Set type bindings.
- LIST<ASCII>, SET<ASCII> (Vec<String>)
- LIST<TEXT>, SET<TEXT> (Vec<String>)
- LIST<BOOLEAN>, SET<BOOLEAN> (Vec<bool>)
- LIST<TINYINT>, SET<TINYINT> (Vec<i8>)
- LIST<SMALLINT>, SET<SMALLINT> (Vec<i16>)
- LIST<INT>, SET<INT> (Vec<i32>)
- LIST<BIGINT>, SET<BIGINT> (Vec<i64>)
- LIST<FLOAT>, SET<FLOAT> (Vec<f32>)
- LIST<DOUBLE>, SET<DOUBLE> (Vec<f64>)
- LIST<BLOB>, SET<BLOB> (Vec<Vec<u8>>)
- LIST<UUID>, SET<UUID> (Vec<uuid::Uuid>)
- LIST<TIMEUUID>, SET<TIMEUUID> (Vec<scylla::value::CqlTimeuuid>)
- LIST<TIMESTAMP>, SET<TIMESTAMP> (Vec<scylla::value::CqlTimestamp>, Vec<chrono::DateTime<Utc>>, Vec<time::OffsetDateTime>)
- LIST<DATE>, SET<DATE> (Vec<scylla::value::CqlDate>, Vec<chrono::NaiveDate>, Vec<time::Date>)
- LIST<TIME>, SET<TIME> (Vec<scylla::value::CqlTime>, Vec<chrono::NaiveTime>, Vec<time::Time>)
- LIST<INET>, SET<INET> (Vec<std::net::IpAddr>)
- LIST<DECIMAL>, SET<DECIMAL> (Vec<bigdecimal::Decimal>)
- LIST<DURATION> (Vec<scylla::value::CqlDuration>)
- Varint
Map type bindings.
- MAP<ASCII, ASCII>, MAP<ASCII, TEXT>, MAP<TEXT, ASCII>, MAP<TEXT, TEXT> (HashMap<String, String>)
- MAP<ASCII, BOOLEAN>, MAP<TEXT, BOOLEAN> (HashMap<String, bool>)
- MAP<ASCII, TINYINT>, MAP<TEXT, TINYINT> (HashMap<String, i8>)
- MAP<ASCII, SMALLINT>, MAP<TEXT, SMALLINT> (HashMap<String, i16>)
- MAP<ASCII, INT>, MAP<TEXT, INT> (HashMap<String, i32>)
- MAP<ASCII, BIGINT>, MAP<TEXT, BIGINT> (HashMap<String, i64>)
- MAP<ASCII, FLOAT>, MAP<TEXT, FLOAT> (HashMap<String, f32>)
- MAP<ASCII, DOUBLE>, MAP<TEXT, DOUBLE> (HashMap<String, f64>)
- MAP<ASCII, UUID>, MAP<TEXT, UUID> (HashMap<String, uuid::Uuid>)
- MAP<ASCII, INET>, MAP<TEXT, INET> (HashMap<String, IpAddr>)
- Define a Rust type with the
UserDefinedTypederive macro. See the example.
The FromRow derive macro supports the same field and container attributes as
SQLx's standard FromRow derive macro, including rename, rename_all,
default, flatten, try_from, json, and skip. It also supports the
#[sqlx(default_when_null)] field attribute, which uses the field type's
Default value when the corresponding database column is NULL.
use sqlx_scylladb::macros::FromRow;
#[derive(FromRow)]
struct User {
id: i64,
#[sqlx(default_when_null)]
display_name: String,
}- Use the
#[sqlx::test]macro for database-backed tests.
- Implements the
sqlx::migrate::Migratorintegration. - Supports migrations used by
#[sqlx::test]. - Provides a command-line tool. Install it with
cargo install --git https://github.com/masato-hi/sqlx-scylladb --path sqlx-scylladb-cli.
- TLS is available when the
openssl-010orrustls-023feature is enabled.
Transactions are implemented by collecting data-changing statements and executing them as a ScyllaDB batch when the transaction is committed.
Because of this implementation, read the ScyllaDB documentation on batch operations before relying on transactions. Batch statements have different performance and atomicity characteristics from transactions in traditional relational databases.
In the benchmark included in this repository, performance is approximately 5–10% lower than when using the scylla-rust-driver directly, depending on the data type and operation.
Each benchmark performs 10,000 operations. In the results below, the difference between the two implementations is approximately 17–33 milliseconds. Actual results depend on the workload and environment.
Each benchmark executes 10,000 sequential operations per Criterion iteration. Table setup, connection or pool creation, and data preparation for SELECT benchmarks are excluded from the measured time. Value generation for INSERT benchmarks is included. The comparison uses ScyllaDB's CachingSession and SQLx's ScyllaDBPool with up to 8 connections.
Benchmark results.
| Type | Operation | Crate | Lower bound | Estimate | Upper bound | Benchmark Name |
|---|---|---|---|---|---|---|
| Text | INSERT | scylla-rust-driver | 302.86 ms | 304.94 ms | 307.55 ms | insert_text_with_scylla |
| Text | INSERT | sqlx-scylladb | 321.82 ms | 323.95 ms | 326.36 ms | insert_text_with_sqlx_scylladb |
| Text | SELECT | scylla-rust-driver | 301.21 ms | 302.00 ms | 302.83 ms | select_text_with_scylla |
| Text | SELECT | sqlx-scylladb | 320.15 ms | 321.17 ms | 322.22 ms | select_text_with_sqlx_scylladb |
| UUID | INSERT | scylla-rust-driver | 302.72 ms | 304.33 ms | 306.27 ms | insert_uuid_with_scylla |
| UUID | INSERT | sqlx-scylladb | 319.46 ms | 320.84 ms | 322.52 ms | insert_uuid_with_sqlx_scylladb |
| UUID | SELECT | scylla-rust-driver | 301.19 ms | 301.92 ms | 302.65 ms | select_uuid_with_scylla |
| UUID | SELECT | sqlx-scylladb | 320.79 ms | 321.65 ms | 322.53 ms | select_uuid_with_sqlx_scylladb |
| Blob | INSERT | scylla-rust-driver | 332.32 ms | 334.30 ms | 336.77 ms | insert_blob_with_scylla |
| Blob | INSERT | sqlx-scylladb | 365.69 ms | 367.39 ms | 369.51 ms | insert_blob_with_sqlx_scylladb |
| Blob | SELECT | scylla-rust-driver | 310.20 ms | 311.22 ms | 312.37 ms | select_blob_with_scylla |
| Blob | SELECT | sqlx-scylladb | 329.80 ms | 330.87 ms | 332.13 ms | select_blob_with_sqlx_scylladb |
This project is licensed under either of
Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any Contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.