ScyllaDB University Live | Free Virtual Training Event
Learn more
ScyllaDB Documentation Logo Documentation
  • Server
  • Cloud
  • Tools
    • ScyllaDB Manager
    • ScyllaDB Monitoring Stack
    • ScyllaDB Operator
  • Drivers
    • CQL Drivers
    • DynamoDB Drivers
  • Resources
    • ScyllaDB University
    • Community Forum
    • Tutorials
Download
ScyllaDB Docs Scylla Rust Driver Data Types User defined types

Caution

You're viewing documentation for a deprecated version of Scylla Rust Driver. Switch to the latest stable version.

User defined types¶

Scylla allows users to define their own data types with named fields (See the official documentation)
To use user defined types in the driver, you can create a corresponding struct in Rust, and use it to read and write UDT values.

For example let’s say my_type was created using this query:

CREATE TYPE ks.my_type (int_val int, text_val text)

To use this type in the driver, create a matching struct and derive:

  • SerializeValue: in order to be able to use this struct in query parameters. \

  • DeserializeValue: in order to be able to use this struct in query results. \

Both macros require fields of UDT and struct to have matching names, but the order of the fields is not required to be the same.
Note: you can use different name using rename attribute - see SerializeValue and DeserializeValue macros documentation.

use scylla::{DeserializeValue, SerializeValue};

// Define a custom struct that matches the User Defined Type created earlier.
// Fields don't have to be in the same order as they are in the database.
// By default, they must have the same names, but this can be worked around
// using `#[rename] field attribute.
// Wrapping a field in Option will gracefully handle null field values.
#[derive(Debug, DeserializeValue, SerializeValue)]
struct MyType {
    int_val: i32,
    text_val: Option<String>,
}

Important
For (de)serialization, by default fields in the Rust struct must be defined with the same names as they are in the database. The driver will (de)serialize the fields in the order defined by the UDT, matching Rust fields by name. You can change this behaviour using macro attributes, see SerializeValue/DeserializeValue macro documentation for more information.

Now it can be sent and received just like any other CQL value:

use futures::TryStreamExt;
use scylla::{DeserializeValue, SerializeValue};

#[derive(Debug, DeserializeValue, SerializeValue)]
struct MyType {
    int_val: i32,
    text_val: Option<String>,
}

// Insert my_type into the table
let to_insert = MyType {
    int_val: 17,
    text_val: Some("Some string".to_string()),
};

session
    .query_unpaged("INSERT INTO keyspace.table (a) VALUES(?)", (to_insert,))
    .await?;

// Read MyType from the table
let mut iter = session.query_iter("SELECT a FROM keyspace.table", &[])
    .await?
    .rows_stream::<(MyType,)>()?;
while let Some((my_type_value,)) = iter.try_next().await? {
    println!("{:?}", my_type_value);
}

Was this page helpful?

PREVIOUS
Tuple
NEXT
Load balancing
  • Create an issue
  • Edit this page
Scylla Rust Driver
  • v1.0.0
    • main
    • v1.1.0
    • v1.0.0
  • Scylla Rust Driver
  • Quick Start
    • Creating a project
    • Connecting and running a simple query
    • Running Scylla using Docker
  • Connecting to the cluster
    • Compression
    • Authentication
    • TLS
  • Executing CQL statements - best practices
    • Unprepared statement
    • Statement values
    • Query result
    • Prepared statement
    • Batch statement
    • Paged query
    • USE keyspace
    • Schema agreement
    • Lightweight transaction (LWT) statement
    • Request timeouts
    • Timestamp generators
  • Execution profiles
    • Creating a profile and setting it
    • All options supported by a profile
    • Priorities of execution settings
    • Remapping execution profile handles
  • Data Types
    • Bool, Tinyint, Smallint, Int, Bigint, Float, Double
    • Ascii, Text, Varchar
    • Counter
    • Blob
    • Inet
    • Uuid
    • Timeuuid
    • Date
    • Time
    • Timestamp
    • Duration
    • Decimal
    • Varint
    • List, Set, Map
    • Tuple
    • User defined types
  • Load balancing
    • DefaultPolicy
  • Retry policy configuration
    • Fallthrough retry policy
    • Default retry policy
    • Downgrading consistency retry policy
  • Speculative execution
    • Simple speculative execution
    • Percentile speculative execution
  • Driver metrics
  • Migration guides
    • Adjusting code to changes in serialization API introduced in 0.11
    • Adjusting code to changes in deserialization API introduced in 0.15
  • Logging
  • Query tracing
    • Tracing a simple/prepared/batch query
    • Tracing a paged query
    • Tracing Session::prepare
    • Query Execution History
  • Schema
Docs Tutorials University Contact Us About Us
© 2025, ScyllaDB. All rights reserved. | Terms of Service | Privacy Policy | ScyllaDB, and ScyllaDB Cloud, are registered trademarks of ScyllaDB, Inc.
Last updated on 08 May 2025.
Powered by Sphinx 7.4.7 & ScyllaDB Theme 1.8.6