use super::super::select_optimizer::SSTablePredicate;
use crate::storage::sstable::PartitionKeyShape;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct SchemalessPointSeek {
pub bytes: Vec<u8>,
pub pk_name: String,
pub pk_cql_type: String,
}
pub(super) fn classify_schemaless_point_lookup(
predicates: &[SSTablePredicate],
shape: Option<&PartitionKeyShape>,
) -> Option<SchemalessPointSeek> {
use super::super::select_optimizer::SSTableFilterOp;
let [predicate] = predicates else {
return None;
};
if predicate.is_token() || !matches!(predicate.operation, SSTableFilterOp::Equal) {
return None;
}
let [value] = predicate.values.as_slice() else {
return None;
};
let shape = shape?;
let is_confirmed_sole_pk = shape.partition_key_count == 1
&& shape.clustering_key_count == 0
&& !shape.non_key_column_names.contains(&predicate.column);
if !is_confirmed_sole_pk {
return None;
}
let component = shape.single_pk_component.as_ref()?;
let bytes = crate::storage::partition_key_codec::encode_single_component_key_typed(
value,
&component.cql_type,
)
.ok()?;
Some(SchemalessPointSeek {
bytes,
pk_name: component.name.clone(),
pk_cql_type: component.cql_type.clone(),
})
}
pub(super) fn finalize_schemaless_seek_row(
key: crate::types::RowKey,
value: crate::types::ScanRow,
projection: &[String],
predicates: &[SSTablePredicate],
seek: &SchemalessPointSeek,
) -> Option<crate::query::result::QueryRow> {
use super::predicate::evaluate_predicates;
use super::row_build::build_row_from_scan;
let comparator = crate::types::ComparatorType::from_data_type(&seek.pk_cql_type).ok()?;
let pk_value =
crate::storage::partition_key_codec::deserialize_value_bytes(&key.0, &comparator).ok()?;
let mut row = build_row_from_scan(key, value, projection, None)?;
let pk_name: std::sync::Arc<str> = seek.pk_name.as_str().into();
let already_present = row.values.contains_key(&pk_name);
if !already_present {
row.values.insert(pk_name.clone(), pk_value);
}
if !evaluate_predicates(&row, predicates).ok()? {
return None;
}
if !already_present
&& !projection.is_empty()
&& !projection.iter().any(|p| p.as_str() == seek.pk_name)
{
row.values.remove(&pk_name);
}
Some(row)
}
#[cfg(test)]
mod tests {
use super::super::super::select_optimizer::{SSTableFilterOp, SSTablePredicate};
use super::*;
use super::super::super::select_optimizer::SSTablePredicate as Pred;
use crate::query::result::QueryRow;
use crate::storage::sstable::PartitionKeyComponent;
use crate::types::{RowKey, ScanRow, Value};
use std::sync::Arc;
fn simple_table_shape() -> PartitionKeyShape {
PartitionKeyShape {
partition_key_count: 1,
clustering_key_count: 0,
non_key_column_names: ["name".to_string(), "age".to_string()]
.into_iter()
.collect(),
single_pk_component: Some(PartitionKeyComponent {
name: "id".to_string(),
cql_type: "uuid".to_string(),
}),
}
}
fn int_pk_shape() -> PartitionKeyShape {
PartitionKeyShape {
partition_key_count: 1,
clustering_key_count: 0,
non_key_column_names: ["v".to_string()].into_iter().collect(),
single_pk_component: Some(PartitionKeyComponent {
name: "partition_key".to_string(),
cql_type: "int".to_string(),
}),
}
}
#[test]
fn classify_schemaless_point_lookup_targets_confirmed_pk_equality() {
let shape = simple_table_shape();
let uuid = [7u8; 16];
let predicate =
SSTablePredicate::column("id", SSTableFilterOp::Equal, vec![Value::Uuid(uuid)]);
let seek = classify_schemaless_point_lookup(std::slice::from_ref(&predicate), Some(&shape))
.expect("a single UUID `=` on the confirmed pk must classify");
assert_eq!(seek.bytes, uuid.to_vec(), "raw 16-byte uuid key");
assert_eq!(seek.pk_name, "id");
assert_eq!(seek.pk_cql_type, "uuid");
let int_shape = int_pk_shape();
let int_pred = SSTablePredicate::column(
"partition_key",
SSTableFilterOp::Equal,
vec![Value::BigInt(42)],
);
let int_seek =
classify_schemaless_point_lookup(std::slice::from_ref(&int_pred), Some(&int_shape))
.expect("int pk `=` must classify");
assert_eq!(
int_seek.bytes,
42i32.to_be_bytes().to_vec(),
"a BigInt literal on an int pk must encode to the 4-byte int key (roborev 3784)",
);
assert_eq!(int_seek.bytes.len(), 4);
}
#[test]
fn classify_schemaless_point_lookup_declines_type_mismatch() {
let shape = simple_table_shape(); let text_on_uuid = SSTablePredicate::column(
"id",
SSTableFilterOp::Equal,
vec![Value::text("not-a-uuid".to_string())],
);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&text_on_uuid), Some(&shape)),
None,
"a text literal on a uuid pk must decline (no provable key encoding)",
);
}
#[test]
fn classify_schemaless_point_lookup_rejects_non_pk_column_equality() {
let shape = simple_table_shape();
let name_eq = SSTablePredicate::column(
"name",
SSTableFilterOp::Equal,
vec![Value::text("Mr. James Hoffman".to_string())],
);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&name_eq), Some(&shape)),
None,
"a regular-column equality must NOT take the pk-key seek; it must full-scan",
);
}
#[test]
fn classify_schemaless_point_lookup_requires_single_component_point_shape() {
let value = vec![Value::Uuid([1u8; 16])];
let pred = SSTablePredicate::column("id", SSTableFilterOp::Equal, value);
let composite = PartitionKeyShape {
partition_key_count: 2,
clustering_key_count: 0,
non_key_column_names: Default::default(),
single_pk_component: None,
};
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&pred), Some(&composite)),
None,
);
let clustered = PartitionKeyShape {
partition_key_count: 1,
clustering_key_count: 1,
non_key_column_names: Default::default(),
single_pk_component: Some(PartitionKeyComponent {
name: "id".to_string(),
cql_type: "uuid".to_string(),
}),
};
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&pred), Some(&clustered)),
None,
);
let no_type = PartitionKeyShape {
partition_key_count: 1,
clustering_key_count: 0,
non_key_column_names: Default::default(),
single_pk_component: None,
};
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&pred), Some(&no_type)),
None,
);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&pred), None),
None,
);
}
#[test]
fn classify_schemaless_point_lookup_rejects_non_point_shapes() {
let shape = simple_table_shape();
let s = Some(&shape);
assert_eq!(classify_schemaless_point_lookup(&[], s), None);
let range = SSTablePredicate::column("id", SSTableFilterOp::Gt, vec![Value::Integer(1)]);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&range), s),
None
);
let in_pred = SSTablePredicate::column(
"id",
SSTableFilterOp::In,
vec![Value::Integer(1), Value::Integer(2)],
);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&in_pred), s),
None
);
let a = SSTablePredicate::column("pk", SSTableFilterOp::Equal, vec![Value::Integer(1)]);
let b = SSTablePredicate::column("ck", SSTableFilterOp::Equal, vec![Value::Integer(2)]);
assert_eq!(classify_schemaless_point_lookup(&[a, b], s), None);
let tok = SSTablePredicate::token(
vec!["id".to_string()],
SSTableFilterOp::Equal,
vec![Value::BigInt(5)],
);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&tok), s),
None
);
let blob = SSTablePredicate::column(
"id",
SSTableFilterOp::Equal,
vec![Value::blob(vec![1, 2, 3])],
);
assert_eq!(
classify_schemaless_point_lookup(std::slice::from_ref(&blob), s),
None
);
}
fn scan_row(cells: &[(&str, Value)]) -> ScanRow {
ScanRow::Row(
cells
.iter()
.map(|(n, v)| (Arc::<str>::from(*n), v.clone()))
.collect(),
)
}
#[test]
fn finalize_seek_row_guards_on_reconstructed_pk() {
let seek = SchemalessPointSeek {
bytes: 42i32.to_be_bytes().to_vec(),
pk_name: "partition_key".to_string(),
pk_cql_type: "int".to_string(),
};
let key = RowKey::new(42i32.to_be_bytes().to_vec());
let value = scan_row(&[("v", Value::text("hi".to_string()))]);
let pk_pred = vec![Pred::column(
"partition_key",
SSTableFilterOp::Equal,
vec![Value::BigInt(42)],
)];
let row: QueryRow =
finalize_schemaless_seek_row(key.clone(), value.clone(), &[], &pk_pred, &seek)
.expect("pk-name predicate must match the reconstructed row");
assert_eq!(row.values.get("partition_key"), Some(&Value::Integer(42)));
assert_eq!(row.values.get("v"), Some(&Value::text("hi".to_string())));
let bogus_pred = vec![Pred::column(
"not_a_column",
SSTableFilterOp::Equal,
vec![Value::BigInt(42)],
)];
assert!(
finalize_schemaless_seek_row(key, value, &[], &bogus_pred, &seek).is_none(),
"a nonexistent predicate column must yield 0 rows post-seek (roborev 3784 FINDING 1)",
);
}
#[test]
fn finalize_seek_row_honours_projection_for_output() {
let seek = SchemalessPointSeek {
bytes: 7i32.to_be_bytes().to_vec(),
pk_name: "partition_key".to_string(),
pk_cql_type: "int".to_string(),
};
let key = RowKey::new(7i32.to_be_bytes().to_vec());
let value = scan_row(&[("v", Value::text("x".to_string()))]);
let pk_pred = vec![Pred::column(
"partition_key",
SSTableFilterOp::Equal,
vec![Value::BigInt(7)],
)];
let row = finalize_schemaless_seek_row(key, value, &["v".to_string()], &pk_pred, &seek)
.expect("row passes the guard");
assert!(
!row.values.contains_key("partition_key"),
"pk excluded from projection must not appear in output",
);
assert_eq!(row.values.get("v"), Some(&Value::text("x".to_string())));
}
}