Skip to main content
Primitive types are the basic building blocks of CQL data types. This page covers integers, floating-point numbers, booleans, blobs, and special numeric types.

Integer Types

CQL provides several fixed-size integer types that map directly to Rust’s primitive integer types.

TinyInt

8-bit signed integer.
use scylla::{Session, SerializeValue, DeserializeValue};

// CQL: tinyint
// Rust: i8
let value: i8 = 42;

session.query_unpaged(
    "INSERT INTO table (id, tiny_val) VALUES (?, ?)",
    (1, value),
).await?;

// Read back
let result = session
    .query_unpaged("SELECT tiny_val FROM table WHERE id = 1", &[])
    .await?;

if let Some(row) = result.rows()?.first() {
    let tiny_val: i8 = row.columns[0]
        .as_ref()
        .and_then(|v| v.as_tinyint())
        .unwrap();
    println!("Value: {}", tiny_val);
}

SmallInt

16-bit signed integer.
// CQL: smallint
// Rust: i16
let value: i16 = 1000;

session.query_unpaged(
    "INSERT INTO table (id, small_val) VALUES (?, ?)",
    (1, value),
).await?;

Int

32-bit signed integer. This is the default integer type in CQL.
// CQL: int
// Rust: i32
let value: i32 = 100_000;

session.query_unpaged(
    "INSERT INTO table (id, int_val) VALUES (?, ?)",
    (1, value),
).await?;

BigInt

64-bit signed integer.
// CQL: bigint
// Rust: i64
let value: i64 = 9_223_372_036_854_775_807;

session.query_unpaged(
    "INSERT INTO table (id, big_val) VALUES (?, ?)",
    (1, value),
).await?;

Varint

Arbitrary-precision signed integer. CQL represents this as a two’s complement big-endian byte array.
use scylla::value::CqlVarint;

// Using the native CqlVarint type
let bytes = vec![0x01, 0x02, 0x03];
let varint = CqlVarint::from_signed_bytes_be(bytes);

session.query_unpaged(
    "INSERT INTO table (id, varint_val) VALUES (?, ?)",
    (1, varint),
).await?;

// Reading back
let result = session
    .query_unpaged("SELECT varint_val FROM table WHERE id = 1", &[])
    .await?;

if let Some(row) = result.rows()?.first() {
    let varint_val: CqlVarint = row.columns[0]
        .as_ref()
        .and_then(|v| v.clone().into_cql_varint())
        .unwrap();
    let bytes = varint_val.into_signed_bytes_be();
    println!("Varint bytes: {:?}", bytes);
}

Using num_bigint (Optional)

For more convenient varint operations, enable the num-bigint-03 or num-bigint-04 feature:
[dependencies]
scylla = { version = "*", features = ["num-bigint-04"] }
num-bigint = "0.4"
use num_bigint::BigInt;

let big_number: BigInt = "123456789012345678901234567890".parse().unwrap();

session.query_unpaged(
    "INSERT INTO table (id, varint_val) VALUES (?, ?)",
    (1, big_number),
).await?;

Floating-Point Types

Float

32-bit IEEE-754 floating point number.
// CQL: float
// Rust: f32
let value: f32 = 3.14159;

session.query_unpaged(
    "INSERT INTO table (id, float_val) VALUES (?, ?)",
    (1, value),
).await?;

Double

64-bit IEEE-754 floating point number.
// CQL: double
// Rust: f64
let value: f64 = 2.718281828459045;

session.query_unpaged(
    "INSERT INTO table (id, double_val) VALUES (?, ?)",
    (1, value),
).await?;

Boolean

Boolean value (true or false).
// CQL: boolean
// Rust: bool
let value: bool = true;

session.query_unpaged(
    "INSERT INTO table (id, bool_val) VALUES (?, ?)",
    (1, value),
).await?;

Blob

Binary data of arbitrary length. CQL blobs map to various Rust byte containers.
use bytes::Bytes;

// Using Vec<u8>
let data: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
session.query_unpaged(
    "INSERT INTO table (id, blob_val) VALUES (?, ?)",
    (1, data),
).await?;

// Using &[u8]
let data: &[u8] = &[0x01, 0x02, 0x03, 0x04];
session.query_unpaged(
    "INSERT INTO table (id, blob_val) VALUES (?, ?)",
    (1, data),
).await?;

// Using Bytes (more efficient for large data)
let data = Bytes::from(vec![0x01, 0x02, 0x03, 0x04]);
session.query_unpaged(
    "INSERT INTO table (id, blob_val) VALUES (?, ?)",
    (1, data),
).await?;

Decimal

Variable-precision decimal number, represented as an arbitrary-precision integer and a scale.
use scylla::value::CqlDecimal;

// Using the native CqlDecimal type
let bytes = vec![0x01, 0x02, 0x03];
let scale: i32 = 2; // Two decimal places
let decimal = CqlDecimal::from_signed_be_bytes_and_exponent(bytes, scale);

session.query_unpaged(
    "INSERT INTO table (id, decimal_val) VALUES (?, ?)",
    (1, decimal),
).await?;

Using bigdecimal (Optional)

For more convenient decimal operations, enable the bigdecimal-04 feature:
[dependencies]
scylla = { version = "*", features = ["bigdecimal-04"] }
bigdecimal = "0.4"
use bigdecimal::BigDecimal;
use std::str::FromStr;

let decimal = BigDecimal::from_str("123.456").unwrap();

session.query_unpaged(
    "INSERT INTO table (id, decimal_val) VALUES (?, ?)",
    (1, decimal),
).await?;

Counter

Counter is a special 64-bit integer type used for distributed counters. Counters can only be incremented or decremented.
use scylla::value::Counter;

// Counters cannot be inserted directly - they must be updated
session.query_unpaged(
    "UPDATE counter_table SET counter_val = counter_val + ? WHERE id = ?",
    (Counter(5), 1),
).await?;

// Reading a counter
let result = session
    .query_unpaged("SELECT counter_val FROM counter_table WHERE id = 1", &[])
    .await?;

if let Some(row) = result.rows()?.first() {
    let counter: Counter = row.columns[0]
        .as_ref()
        .and_then(|v| v.as_counter())
        .unwrap();
    println!("Counter value: {}", counter.0);
}
Important: Counter columns have special requirements:
  • They must be in a table where all non-primary-key columns are counters
  • They can only be updated using UPDATE statements with + or - operations
  • They cannot be part of the primary key

Inet

IPv4 or IPv6 address.
use std::net::IpAddr;

// IPv4
let ipv4: IpAddr = "192.168.1.1".parse().unwrap();
session.query_unpaged(
    "INSERT INTO table (id, ip) VALUES (?, ?)",
    (1, ipv4),
).await?;

// IPv6
let ipv6: IpAddr = "2001:0db8:85a3::8a2e:0370:7334".parse().unwrap();
session.query_unpaged(
    "INSERT INTO table (id, ip) VALUES (?, ?)",
    (2, ipv6),
).await?;

Empty Values

Some primitive types support a special “empty” value (distinct from null) represented as 0 bytes. This is a quirk of CQL where certain types can have an additional value.
use scylla::value::MaybeEmpty;

// Empty value
let empty: MaybeEmpty<i32> = MaybeEmpty::Empty;
session.query_unpaged(
    "INSERT INTO table (id, val) VALUES (?, ?)",
    (1, empty),
).await?;

// Non-empty value
let value: MaybeEmpty<i32> = MaybeEmpty::Value(42);
session.query_unpaged(
    "INSERT INTO table (id, val) VALUES (?, ?)",
    (2, value),
).await?;
Types that support empty values include all numeric types, date/time types, UUID types, and inet.

See Also

Build docs developers (and LLMs) love