Background
When executing a statement through the CQL protocol, values for bind markers are sent in a serialized, untyped form. To implement a safer and more robust interface, drivers can use information returned after preparing a statement to check the type of data provided by the user against the actual types of the bind markers.Problems with the Old API
Before 0.11, the driver couldn’t perform type checking:- No type validation: The driver would naively serialize data and hope the user sent correct types. Type mismatches would either fail on the database side or, worse, be silently reinterpreted as unintended types.
-
UDT field ordering issues: User-Defined Types (UDTs) require fields to be serialized in the same order as defined in the database schema. The old
IntoUserTypemacro expected Rust struct fields to match this order exactly, which was cumbersome to maintain.
The Solution
Version 0.11 introduces new traits that receive more information during serialization, including column/bind marker names and their types. This enables:- Type checking against the database schema
- Automatic field matching by name for UDTs
- Better error messages when type mismatches occur
Old vs. New Traits
Both APIs are based on three core traits:| Old Trait | New Trait | Purpose |
|---|---|---|
Value | SerializeValue | Serialize a single CQL value (e.g., i32 → CQL int) |
ValueList | SerializeRow | Serialize a list of values for a statement (e.g., (i32, &str) for SELECT * FROM t WHERE pk = ? AND ck = ?) |
BatchValues | LegacyBatchValues (old)BatchValues (new) | Provide data for batch requests |
All methods that previously accepted old traits (
Session::query, Session::execute, Session::batch) now accept the new traits.Migration Examples
Basic Value Serialization
Before (0.10 and earlier):Row Serialization for Queries
Before:Using Named Bind Markers
The new API works seamlessly with named bind markers:Macro Attribute Changes
Enforcing Field Order (Legacy Behavior)
If you need the old behavior where fields must be in a specific order:SerializeRow:
Available Attributes
flavor = "enforce_order": Fields must appear in the same order as in the databaseskip_name_checks: Don’t validate field names against column/bind marker names
Important Behavioral Changes
Mandatory Preparation with Non-Empty Values
The new API requires type checking, which means the driver must prepare statements before executing them with non-empty value lists. Impact onSession::query:
- An additional round-trip is incurred to prepare the statement before sending it
- Preparation is skipped if the value list is empty
Session::batch:
- The driver sends a prepare request for each unique unprepared statement with non-empty values
- These requests are sent serially, which can significantly impact performance
Removal of Old API in Version 1.0
Versions 0.11 through 0.x offered both old and new APIs to allow gradual migration. If you’re upgrading directly to 1.0 or later, you must update all code to use:SerializeValueinstead ofValueSerializeRowinstead ofValueListBatchValues(new) instead ofLegacyBatchValues(old)
Summary
The new serialization API in version 0.11 provides:- Better type safety through mandatory type checking
- Improved UDT support with automatic name-based field matching
- More ergonomic API with support for named bind markers
- Clearer error messages when type mismatches occur
