1mod checked;
16
17use std::collections::{HashMap, HashSet};
18use std::sync::Arc;
19
20use bytes::BufMut;
21use common_recordbatch::filter::SimpleFilterEvaluator;
22use datatypes::prelude::ConcreteDataType;
23use datatypes::value::{Value, ValueRef};
24use memcomparable::{Deserializer, Serializer};
25use serde::{Deserialize, Serialize};
26use snafu::{OptionExt, ResultExt, ensure};
27use store_api::codec::PrimaryKeyEncoding;
28use store_api::metadata::RegionMetadataRef;
29use store_api::storage::ColumnId;
30use store_api::storage::consts::ReservedColumnId;
31
32use crate::error::{
33 DeserializeFieldSnafu, InvalidSparsePrimaryKeySnafu, Result, SerializeFieldSnafu,
34 UnsupportedOperationSnafu,
35};
36use crate::key_values::KeyValue;
37use crate::primary_key_filter::SparsePrimaryKeyFilter;
38use crate::row_converter::dense::SortField;
39pub use crate::row_converter::sparse::checked::SparsePrimaryKeyView;
40use crate::row_converter::{CompositeValues, PrimaryKeyCodec, PrimaryKeyFilter};
41
42#[derive(Clone, Debug)]
57pub struct SparsePrimaryKeyCodec {
58 inner: Arc<SparsePrimaryKeyCodecInner>,
59}
60
61#[derive(Debug, Clone)]
62struct SparsePrimaryKeyCodecInner {
63 fields: Option<Vec<(ColumnId, SortField)>>,
64 table_id_field: SortField,
66 tsid_field: SortField,
68 label_field: SortField,
70 columns: Option<HashSet<ColumnId>>,
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Default)]
81pub struct SparseValues {
82 values: Vec<(ColumnId, Value)>,
83}
84
85impl SparseValues {
86 pub fn new() -> Self {
88 Self { values: Vec::new() }
89 }
90
91 pub fn with_capacity(cap: usize) -> Self {
93 Self {
94 values: Vec::with_capacity(cap),
95 }
96 }
97
98 pub fn get_or_null(&self, column_id: ColumnId) -> &Value {
100 for (id, value) in &self.values {
101 if *id == column_id {
102 return value;
103 }
104 }
105 &Value::Null
106 }
107
108 pub fn get(&self, column_id: &ColumnId) -> Option<&Value> {
110 for (id, value) in &self.values {
111 if id == column_id {
112 return Some(value);
113 }
114 }
115 None
116 }
117
118 pub fn insert(&mut self, column_id: ColumnId, value: Value) {
122 self.values.push((column_id, value));
123 }
124
125 pub fn iter(&self) -> impl Iterator<Item = (&ColumnId, &Value)> {
127 self.values.iter().map(|(id, value)| (id, value))
128 }
129}
130
131pub const RESERVED_COLUMN_ID_TSID: ColumnId = ReservedColumnId::tsid();
133pub const RESERVED_COLUMN_ID_TABLE_ID: ColumnId = ReservedColumnId::table_id();
135pub const COLUMN_ID_ENCODE_SIZE: usize = 4;
137
138const TABLE_ID_VALUE_OFFSET: usize = COLUMN_ID_ENCODE_SIZE;
142const TSID_VALUE_OFFSET: usize = COLUMN_ID_ENCODE_SIZE + 5 + COLUMN_ID_ENCODE_SIZE;
144const TAGS_START_OFFSET: usize = COLUMN_ID_ENCODE_SIZE + 5 + COLUMN_ID_ENCODE_SIZE + 9;
146
147#[derive(Default)]
151pub struct SparsePrimaryKeyValidator {
152 column_ids: Vec<ColumnId>,
153 label_buf: Vec<u8>,
154}
155
156impl SparsePrimaryKeyValidator {
157 pub fn validate(&mut self, bytes: &[u8]) -> Result<()> {
159 self.column_ids.clear();
160 validate_prefix(bytes)?;
161 let mut remaining = &bytes[TAGS_START_OFFSET..];
162 while !remaining.is_empty() {
163 let id = remaining.first_chunk::<COLUMN_ID_ENCODE_SIZE>().context(
164 InvalidSparsePrimaryKeySnafu {
165 reason: "truncated label column id",
166 },
167 )?;
168 let column_id = u32::from_be_bytes(*id);
169 ensure!(
170 !ReservedColumnId::is_reserved(column_id),
171 InvalidSparsePrimaryKeySnafu {
172 reason: "reserved column id in sparse labels",
173 }
174 );
175 self.column_ids.push(column_id);
176 let encoded = &remaining[COLUMN_ID_ENCODE_SIZE..];
177 let (length, ascii) = crate::row_converter::encoded_string_info::<true>(encoded)
178 .context(DeserializeFieldSnafu)?;
179 let encoded = &encoded[..length];
180 if !ascii {
182 self.label_buf.clear();
183 self.label_buf.reserve(length);
184 Deserializer::new(&encoded[1..])
185 .read_bytes_into(&mut self.label_buf)
186 .context(DeserializeFieldSnafu)?;
187 std::str::from_utf8(&self.label_buf).map_err(|_| {
188 InvalidSparsePrimaryKeySnafu {
189 reason: "label is not valid UTF-8",
190 }
191 .build()
192 })?;
193 }
194 remaining = &remaining[COLUMN_ID_ENCODE_SIZE + length..];
195 }
196 self.column_ids.sort_unstable();
197 ensure!(
198 !self.column_ids.windows(2).any(|pair| pair[0] == pair[1]),
199 InvalidSparsePrimaryKeySnafu {
200 reason: "duplicate column id in sparse key",
201 }
202 );
203 Ok(())
204 }
205}
206
207const SPARSE_OFFSETS_INLINE_CAP: usize = 32;
213
214#[derive(Debug, Clone)]
216pub struct SparseOffsetsCache {
217 inline: Vec<(ColumnId, usize)>,
220 overflow: HashMap<ColumnId, usize>,
222 cursor: usize,
224 finished: bool,
227}
228
229impl Default for SparseOffsetsCache {
230 fn default() -> Self {
231 Self::new()
232 }
233}
234
235impl SparseOffsetsCache {
236 pub fn new() -> Self {
237 Self {
238 inline: Vec::new(),
239 overflow: HashMap::new(),
240 cursor: TAGS_START_OFFSET,
241 finished: false,
242 }
243 }
244
245 pub fn clear(&mut self) {
246 self.inline.clear();
247 self.overflow.clear();
248 self.cursor = TAGS_START_OFFSET;
249 self.finished = false;
250 }
251
252 fn get(&self, column_id: ColumnId) -> Option<usize> {
254 for entry in &self.inline {
255 if entry.0 == column_id {
256 return Some(entry.1);
257 }
258 }
259 self.overflow.get(&column_id).copied()
260 }
261
262 fn insert(&mut self, column_id: ColumnId, offset: usize) {
264 if self.inline.len() < SPARSE_OFFSETS_INLINE_CAP {
265 if self.inline.capacity() == 0 {
266 self.inline.reserve_exact(SPARSE_OFFSETS_INLINE_CAP);
267 }
268 self.inline.push((column_id, offset));
269 } else {
270 self.overflow.insert(column_id, offset);
271 }
272 }
273
274 #[cfg(test)]
275 fn contains(&self, column_id: ColumnId) -> bool {
276 self.get(column_id).is_some()
277 }
278}
279
280impl SparsePrimaryKeyCodec {
281 pub fn from_columns(columns_ids: impl Iterator<Item = ColumnId>) -> Self {
283 let columns = columns_ids.collect();
284 Self {
285 inner: Arc::new(SparsePrimaryKeyCodecInner {
286 fields: None,
287 table_id_field: SortField::new(ConcreteDataType::uint32_datatype()),
288 tsid_field: SortField::new(ConcreteDataType::uint64_datatype()),
289 label_field: SortField::new(ConcreteDataType::string_datatype()),
290 columns: Some(columns),
291 }),
292 }
293 }
294
295 pub fn new(region_metadata: &RegionMetadataRef) -> Self {
297 let fields = region_metadata
298 .primary_key_columns()
299 .map(|c| {
300 (
301 c.column_id,
302 SortField::new(c.column_schema.data_type.clone()),
303 )
304 })
305 .collect();
306 Self::with_fields(fields)
307 }
308
309 pub fn schemaless() -> Self {
313 Self {
314 inner: Arc::new(SparsePrimaryKeyCodecInner {
315 fields: None,
316 table_id_field: SortField::new(ConcreteDataType::uint32_datatype()),
317 tsid_field: SortField::new(ConcreteDataType::uint64_datatype()),
318 label_field: SortField::new(ConcreteDataType::string_datatype()),
319 columns: None,
320 }),
321 }
322 }
323
324 pub fn with_fields(fields: Vec<(ColumnId, SortField)>) -> Self {
326 let mut codec = Self::from_columns(fields.iter().map(|f| f.0));
327 Arc::make_mut(&mut codec.inner).fields = Some(fields);
328 codec
329 }
330
331 fn get_field(&self, column_id: ColumnId) -> Option<&SortField> {
333 if let Some(columns) = &self.inner.columns
334 && !columns.contains(&column_id)
335 {
336 return None;
337 }
338 match column_id {
339 RESERVED_COLUMN_ID_TABLE_ID => Some(&self.inner.table_id_field),
340 RESERVED_COLUMN_ID_TSID => Some(&self.inner.tsid_field),
341 _ => Some(&self.inner.label_field),
342 }
343 }
344
345 pub fn encode_to_vec<'a, I>(&self, row: I, buffer: &mut Vec<u8>) -> Result<()>
347 where
348 I: Iterator<Item = (ColumnId, ValueRef<'a>)>,
349 {
350 let mut serializer = Serializer::new(buffer);
351 for (column_id, value) in row {
352 if value.is_null() {
353 continue;
354 }
355
356 if let Some(field) = self.get_field(column_id) {
357 column_id
358 .serialize(&mut serializer)
359 .context(SerializeFieldSnafu)?;
360 field.serialize(&mut serializer, &value)?;
361 } else {
362 common_telemetry::warn!("Column {} is not in primary key, skipping", column_id);
364 }
365 }
366 Ok(())
367 }
368
369 pub fn encode_raw_tag_value<'a, I>(&self, row: I, buffer: &mut Vec<u8>) -> Result<()>
370 where
371 I: Iterator<Item = (ColumnId, &'a [u8])>,
372 {
373 for (tag_column_id, tag_value) in row {
374 let value_len = tag_value.len();
375 buffer.reserve(6 + value_len.div_ceil(8) * 9);
376 buffer.put_u32(tag_column_id);
377 buffer.put_u8(1);
378 buffer.put_u8(!tag_value.is_empty() as u8);
379
380 let mut len = 0;
383 let num_chucks = value_len / 8;
384 let remainder = value_len % 8;
385
386 for idx in 0..num_chucks {
387 buffer.extend_from_slice(&tag_value[idx * 8..idx * 8 + 8]);
388 len += 8;
389 let extra = if len == value_len { 8 } else { 9 };
393 buffer.put_u8(extra);
394 }
395
396 if remainder != 0 {
397 buffer.extend_from_slice(&tag_value[len..value_len]);
398 buffer.put_bytes(0, 8 - remainder);
399 buffer.put_u8(remainder as u8);
400 }
401 }
402 Ok(())
403 }
404
405 pub fn encode_internal(&self, table_id: u32, tsid: u64, buffer: &mut Vec<u8>) -> Result<()> {
407 buffer.reserve_exact(22);
408 buffer.put_u32(RESERVED_COLUMN_ID_TABLE_ID);
409 buffer.put_u8(1);
410 buffer.put_u32(table_id);
411 buffer.put_u32(RESERVED_COLUMN_ID_TSID);
412 buffer.put_u8(1);
413 buffer.put_u64(tsid);
414 Ok(())
415 }
416
417 pub fn decode_ids(&self, bytes: &[u8]) -> Result<(u32, u64)> {
419 const INTERNAL_PREFIX_LEN: usize = 4 + 1 + 4 + 4 + 1 + 8;
421 ensure!(
422 bytes.len() >= INTERNAL_PREFIX_LEN,
423 InvalidSparsePrimaryKeySnafu {
424 reason: format!(
425 "internal prefix requires at least {INTERNAL_PREFIX_LEN} bytes, got {}",
426 bytes.len()
427 ),
428 }
429 );
430
431 let mut deserializer = Deserializer::new(bytes);
432
433 let table_id_column = u32::deserialize(&mut deserializer).context(DeserializeFieldSnafu)?;
434 ensure!(
435 table_id_column == RESERVED_COLUMN_ID_TABLE_ID,
436 InvalidSparsePrimaryKeySnafu {
437 reason: format!(
438 "expected table id column {}, got {}",
439 RESERVED_COLUMN_ID_TABLE_ID, table_id_column
440 ),
441 }
442 );
443 let table_id = self.inner.table_id_field.deserialize(&mut deserializer)?;
444
445 let tsid_column = u32::deserialize(&mut deserializer).context(DeserializeFieldSnafu)?;
446 ensure!(
447 tsid_column == RESERVED_COLUMN_ID_TSID,
448 InvalidSparsePrimaryKeySnafu {
449 reason: format!(
450 "expected tsid column {}, got {}",
451 RESERVED_COLUMN_ID_TSID, tsid_column
452 ),
453 }
454 );
455 let tsid = self.inner.tsid_field.deserialize(&mut deserializer)?;
456
457 match (table_id, tsid) {
458 (Value::UInt32(table_id), Value::UInt64(tsid)) => Ok((table_id, tsid)),
459 (table_id, tsid) => InvalidSparsePrimaryKeySnafu {
460 reason: format!(
461 "expected UInt32 table id and UInt64 tsid, got {table_id:?} and {tsid:?}"
462 ),
463 }
464 .fail(),
465 }
466 }
467
468 fn decode_sparse(&self, bytes: &[u8]) -> Result<SparseValues> {
470 let mut values = SparseValues::with_capacity(16);
471 let (table_id, tsid) = self.decode_ids(bytes)?;
472 values.insert(RESERVED_COLUMN_ID_TABLE_ID, Value::UInt32(table_id));
473 values.insert(RESERVED_COLUMN_ID_TSID, Value::UInt64(tsid));
474 let mut remaining = &bytes[TAGS_START_OFFSET..];
475 while !remaining.is_empty() {
476 let id = remaining.first_chunk::<COLUMN_ID_ENCODE_SIZE>().context(
477 InvalidSparsePrimaryKeySnafu {
478 reason: "truncated label column id",
479 },
480 )?;
481 let column_id = u32::from_be_bytes(*id);
482 ensure!(
483 !ReservedColumnId::is_reserved(column_id),
484 InvalidSparsePrimaryKeySnafu {
485 reason: "reserved column id in sparse labels"
486 }
487 );
488 let encoded = &remaining[COLUMN_ID_ENCODE_SIZE..];
489 let length =
490 crate::row_converter::encoded_string_len(encoded).context(DeserializeFieldSnafu)?;
491 let value = self
492 .inner
493 .label_field
494 .deserialize(&mut Deserializer::new(&encoded[..length]))?;
495 ensure!(
496 values.get(&column_id).is_none(),
497 InvalidSparsePrimaryKeySnafu {
498 reason: "duplicate column id in sparse key",
499 }
500 );
501 values.insert(column_id, value);
502 remaining = &encoded[length..];
503 }
504 Ok(values)
505 }
506
507 fn decode_leftmost(&self, bytes: &[u8]) -> Result<Option<Value>> {
509 if bytes.is_empty() {
510 return Ok(None);
511 }
512 self.decode_ids(bytes)
513 .map(|(table_id, _)| Some(Value::UInt32(table_id)))
514 }
515
516 pub fn has_column(
526 &self,
527 pk: &[u8],
528 cache: &mut SparseOffsetsCache,
529 column_id: ColumnId,
530 ) -> Option<usize> {
531 match column_id {
540 RESERVED_COLUMN_ID_TABLE_ID => return Some(TABLE_ID_VALUE_OFFSET),
541 RESERVED_COLUMN_ID_TSID => return Some(TSID_VALUE_OFFSET),
542 _ => {}
543 }
544
545 if let Some(offset) = cache.get(column_id) {
546 return Some(offset);
547 }
548 if cache.finished {
549 return None;
550 }
551
552 let mut deserializer = Deserializer::new(pk);
553 deserializer.advance(cache.cursor);
554 let mut offset = cache.cursor;
555 while deserializer.has_remaining() {
556 let col = u32::deserialize(&mut deserializer).unwrap();
557 offset += COLUMN_ID_ENCODE_SIZE;
558 let value_offset = offset;
559 cache.insert(col, value_offset);
560 let Some(field) = self.get_field(col) else {
561 cache.finished = true;
562 cache.cursor = offset;
563 return None;
564 };
565
566 let skip = field.skip_deserialize(pk, &mut deserializer).unwrap();
567 offset += skip;
568 cache.cursor = offset;
569 if col == column_id {
570 return Some(value_offset);
571 }
572 }
573
574 cache.finished = true;
575 None
576 }
577
578 pub fn decode_value_at(&self, pk: &[u8], offset: usize, column_id: ColumnId) -> Result<Value> {
580 let mut deserializer = Deserializer::new(pk);
581 deserializer.advance(offset);
582 let field = self.get_field(column_id).unwrap();
584 field.deserialize(&mut deserializer)
585 }
586
587 pub fn encoded_value_for_column<'a>(
591 &self,
592 pk: &'a [u8],
593 cache: &mut SparseOffsetsCache,
594 column_id: ColumnId,
595 ) -> Result<Option<&'a [u8]>> {
596 let Some(offset) = self.has_column(pk, cache, column_id) else {
597 return Ok(None);
598 };
599
600 let Some(field) = self.get_field(column_id) else {
601 return Ok(None);
602 };
603
604 let mut deserializer = Deserializer::new(pk);
605 deserializer.advance(offset);
606 let len = field.skip_deserialize(pk, &mut deserializer)?;
607 Ok(Some(&pk[offset..offset + len]))
608 }
609}
610
611impl PrimaryKeyCodec for SparsePrimaryKeyCodec {
612 fn encode_key_value(&self, key_value: &KeyValue, buffer: &mut Vec<u8>) -> Result<()> {
613 let fields = self
614 .inner
615 .fields
616 .as_ref()
617 .context(UnsupportedOperationSnafu {
618 err_msg: "raw row encoding requires primary key metadata",
619 })?;
620 self.encode_to_vec(
621 fields.iter().map(|f| f.0).zip(key_value.primary_keys()),
622 buffer,
623 )
624 }
625
626 fn encode_values(&self, values: &[(ColumnId, Value)], buffer: &mut Vec<u8>) -> Result<()> {
627 self.encode_to_vec(values.iter().map(|v| (v.0, v.1.as_value_ref())), buffer)
628 }
629
630 fn encode_value_refs(
631 &self,
632 values: &[(ColumnId, ValueRef)],
633 buffer: &mut Vec<u8>,
634 ) -> Result<()> {
635 self.encode_to_vec(values.iter().map(|v| (v.0, v.1.clone())), buffer)
636 }
637
638 fn estimated_size(&self) -> Option<usize> {
639 None
640 }
641
642 fn num_fields(&self) -> Option<usize> {
643 None
644 }
645
646 fn encoding(&self) -> PrimaryKeyEncoding {
647 PrimaryKeyEncoding::Sparse
648 }
649
650 fn primary_key_filter(
651 &self,
652 metadata: &RegionMetadataRef,
653 filters: Arc<Vec<SimpleFilterEvaluator>>,
654 ) -> Box<dyn PrimaryKeyFilter> {
655 Box::new(SparsePrimaryKeyFilter::new(
656 metadata.clone(),
657 filters,
658 self.clone(),
659 ))
660 }
661
662 fn decode(&self, bytes: &[u8]) -> Result<CompositeValues> {
663 Ok(CompositeValues::Sparse(self.decode_sparse(bytes)?))
664 }
665
666 fn decode_leftmost(&self, bytes: &[u8]) -> Result<Option<Value>> {
667 self.decode_leftmost(bytes)
668 }
669}
670
671fn validate_prefix(pk: &[u8]) -> Result<()> {
672 ensure!(
673 pk.len() >= TAGS_START_OFFSET
674 && pk[..COLUMN_ID_ENCODE_SIZE] == RESERVED_COLUMN_ID_TABLE_ID.to_be_bytes()
675 && pk[TSID_VALUE_OFFSET - COLUMN_ID_ENCODE_SIZE..TSID_VALUE_OFFSET]
676 == RESERVED_COLUMN_ID_TSID.to_be_bytes()
677 && pk[TABLE_ID_VALUE_OFFSET] == 1
678 && pk[TSID_VALUE_OFFSET] == 1,
679 InvalidSparsePrimaryKeySnafu {
680 reason: "invalid table_id/tsid prefix"
681 }
682 );
683 Ok(())
684}
685
686#[cfg(test)]
687mod tests {
688 use std::sync::Arc;
689
690 use api::v1::SemanticType;
691 use common_query::prelude::{greptime_timestamp, greptime_value};
692 use common_time::Timestamp;
693 use common_time::timestamp::TimeUnit;
694 use datatypes::schema::ColumnSchema;
695 use datatypes::value::{OrderedFloat, Value};
696 use store_api::metadata::{ColumnMetadata, RegionMetadataBuilder};
697 use store_api::metric_engine_consts::{
698 DATA_SCHEMA_TABLE_ID_COLUMN_NAME, DATA_SCHEMA_TSID_COLUMN_NAME,
699 };
700 use store_api::storage::{ColumnId, RegionId};
701
702 use super::*;
703
704 fn test_region_metadata() -> RegionMetadataRef {
705 let mut builder = RegionMetadataBuilder::new(RegionId::new(1, 1));
706 builder
707 .push_column_metadata(ColumnMetadata {
708 column_schema: ColumnSchema::new(
709 DATA_SCHEMA_TABLE_ID_COLUMN_NAME,
710 ConcreteDataType::uint32_datatype(),
711 false,
712 ),
713 semantic_type: SemanticType::Tag,
714 column_id: ReservedColumnId::table_id(),
715 })
716 .push_column_metadata(ColumnMetadata {
717 column_schema: ColumnSchema::new(
718 DATA_SCHEMA_TSID_COLUMN_NAME,
719 ConcreteDataType::uint64_datatype(),
720 false,
721 ),
722 semantic_type: SemanticType::Tag,
723 column_id: ReservedColumnId::tsid(),
724 })
725 .push_column_metadata(ColumnMetadata {
726 column_schema: ColumnSchema::new("pod", ConcreteDataType::string_datatype(), true),
727 semantic_type: SemanticType::Tag,
728 column_id: 1,
729 })
730 .push_column_metadata(ColumnMetadata {
731 column_schema: ColumnSchema::new(
732 "namespace",
733 ConcreteDataType::string_datatype(),
734 true,
735 ),
736 semantic_type: SemanticType::Tag,
737 column_id: 2,
738 })
739 .push_column_metadata(ColumnMetadata {
740 column_schema: ColumnSchema::new(
741 "container",
742 ConcreteDataType::string_datatype(),
743 true,
744 ),
745 semantic_type: SemanticType::Tag,
746 column_id: 3,
747 })
748 .push_column_metadata(ColumnMetadata {
749 column_schema: ColumnSchema::new(
750 "pod_name",
751 ConcreteDataType::string_datatype(),
752 true,
753 ),
754 semantic_type: SemanticType::Tag,
755 column_id: 4,
756 })
757 .push_column_metadata(ColumnMetadata {
758 column_schema: ColumnSchema::new(
759 "pod_ip",
760 ConcreteDataType::string_datatype(),
761 true,
762 ),
763 semantic_type: SemanticType::Tag,
764 column_id: 5,
765 })
766 .push_column_metadata(ColumnMetadata {
767 column_schema: ColumnSchema::new(
768 greptime_value(),
769 ConcreteDataType::float64_datatype(),
770 false,
771 ),
772 semantic_type: SemanticType::Field,
773 column_id: 6,
774 })
775 .push_column_metadata(ColumnMetadata {
776 column_schema: ColumnSchema::new(
777 greptime_timestamp(),
778 ConcreteDataType::timestamp_nanosecond_datatype(),
779 false,
780 ),
781 semantic_type: SemanticType::Timestamp,
782 column_id: 7,
783 })
784 .primary_key(vec![
785 ReservedColumnId::table_id(),
786 ReservedColumnId::tsid(),
787 1,
788 2,
789 3,
790 4,
791 5,
792 ]);
793 let metadata = builder.build().unwrap();
794 Arc::new(metadata)
795 }
796
797 #[test]
798 fn test_sparse_value_new_and_get_or_null() {
799 let mut sparse_value = SparseValues::new();
800 sparse_value.insert(1, Value::Int32(42));
801
802 assert_eq!(sparse_value.get_or_null(1), &Value::Int32(42));
803 assert_eq!(sparse_value.get_or_null(2), &Value::Null);
804 }
805
806 #[test]
807 fn test_sparse_value_insert() {
808 let mut sparse_value = SparseValues::new();
809 sparse_value.insert(1, Value::Int32(42));
810
811 assert_eq!(sparse_value.get_or_null(1), &Value::Int32(42));
812 }
813
814 fn test_row() -> Vec<(ColumnId, ValueRef<'static>)> {
815 vec![
816 (RESERVED_COLUMN_ID_TABLE_ID, ValueRef::UInt32(42)),
817 (
818 RESERVED_COLUMN_ID_TSID,
819 ValueRef::UInt64(123843349035232323),
820 ),
821 (1, ValueRef::String("greptime-frontend-6989d9899-22222")),
823 (2, ValueRef::String("greptime-cluster")),
825 (3, ValueRef::String("greptime-frontend-6989d9899-22222")),
827 (4, ValueRef::String("greptime-frontend-6989d9899-22222")),
829 (5, ValueRef::String("10.10.10.10")),
831 (6, ValueRef::Float64(OrderedFloat(1.0))),
833 (
835 7,
836 ValueRef::Timestamp(Timestamp::new(1618876800000000000, TimeUnit::Nanosecond)),
837 ),
838 ]
839 }
840
841 #[test]
842 fn test_encode_by_short_cuts() {
843 let region_metadata = test_region_metadata();
844 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
845 let mut buffer = Vec::new();
846 let internal_columns = [
847 (RESERVED_COLUMN_ID_TABLE_ID, ValueRef::UInt32(1024)),
848 (RESERVED_COLUMN_ID_TSID, ValueRef::UInt64(42)),
849 ];
850 let tags = [
851 (1, "greptime-frontend-6989d9899-22222"),
852 (2, "greptime-cluster"),
853 (3, "greptime-frontend-6989d9899-22222"),
854 (4, "greptime-frontend-6989d9899-22222"),
855 (5, "10.10.10.10"),
856 ];
857 codec
858 .encode_to_vec(internal_columns.into_iter(), &mut buffer)
859 .unwrap();
860 codec
861 .encode_to_vec(
862 tags.iter()
863 .map(|(col_id, tag_value)| (*col_id, ValueRef::String(tag_value))),
864 &mut buffer,
865 )
866 .unwrap();
867
868 let mut buffer_by_raw_encoding = Vec::new();
869 codec
870 .encode_internal(1024, 42, &mut buffer_by_raw_encoding)
871 .unwrap();
872 let tags: Vec<_> = tags
873 .into_iter()
874 .map(|(col_id, tag_value)| (col_id, tag_value.as_bytes()))
875 .collect();
876 codec
877 .encode_raw_tag_value(
878 tags.iter().map(|(c, b)| (*c, *b)),
879 &mut buffer_by_raw_encoding,
880 )
881 .unwrap();
882 assert_eq!(buffer, buffer_by_raw_encoding);
883 }
884
885 #[test]
886 fn raw_encoding_matches_serde_at_chunk_boundaries() {
887 let codec = SparsePrimaryKeyCodec::schemaless();
888 let mut actual = Vec::new();
889 for len in [0, 7, 8, 9, 15, 16, 17, 1024] {
890 let label = "x".repeat(len);
891 let mut expected = Vec::new();
892 codec.encode_internal(42, 7, &mut expected).unwrap();
893 codec
894 .encode_to_vec([(1, ValueRef::String(&label))].into_iter(), &mut expected)
895 .unwrap();
896 actual.clear();
897 codec.encode_internal(42, 7, &mut actual).unwrap();
898 codec
899 .encode_raw_tag_value([(1, label.as_bytes())].into_iter(), &mut actual)
900 .unwrap();
901 assert_eq!(actual, expected, "label length {len}");
902 }
903 }
904
905 #[test]
906 fn test_encode_to_vec() {
907 let region_metadata = test_region_metadata();
908 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
909 let mut buffer = Vec::new();
910
911 let row = test_row();
912 codec.encode_to_vec(row.into_iter(), &mut buffer).unwrap();
913 assert!(!buffer.is_empty());
914 let sparse_value = codec.decode_sparse(&buffer).unwrap();
915 assert_eq!(
916 sparse_value.get_or_null(RESERVED_COLUMN_ID_TABLE_ID),
917 &Value::UInt32(42)
918 );
919 assert_eq!(
920 sparse_value.get_or_null(1),
921 &Value::String("greptime-frontend-6989d9899-22222".into())
922 );
923 assert_eq!(
924 sparse_value.get_or_null(2),
925 &Value::String("greptime-cluster".into())
926 );
927 assert_eq!(
928 sparse_value.get_or_null(3),
929 &Value::String("greptime-frontend-6989d9899-22222".into())
930 );
931 assert_eq!(
932 sparse_value.get_or_null(4),
933 &Value::String("greptime-frontend-6989d9899-22222".into())
934 );
935 assert_eq!(
936 sparse_value.get_or_null(5),
937 &Value::String("10.10.10.10".into())
938 );
939 }
940
941 #[test]
942 fn test_decode_leftmost() {
943 let region_metadata = test_region_metadata();
944 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
945 let mut buffer = Vec::new();
946 let row = test_row();
947 codec.encode_to_vec(row.into_iter(), &mut buffer).unwrap();
948 assert!(!buffer.is_empty());
949 let result = codec.decode_leftmost(&buffer).unwrap().unwrap();
950 assert_eq!(result, Value::UInt32(42));
951 assert_eq!(codec.decode_leftmost(&[]).unwrap(), None);
952 assert!(
953 codec
954 .decode_leftmost(&buffer[..TAGS_START_OFFSET - 1])
955 .is_err()
956 );
957 }
958
959 #[test]
960 fn test_decode_ids() {
961 let region_metadata = test_region_metadata();
962 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
963 let mut buffer = Vec::new();
964 codec.encode_internal(42, 100, &mut buffer).unwrap();
965
966 assert_eq!((42, 100), codec.decode_ids(&buffer).unwrap());
967
968 let mut invalid = buffer.clone();
969 invalid[0..4].copy_from_slice(&1_u32.to_be_bytes());
970 assert!(codec.decode_ids(&invalid).is_err());
971 assert!(codec.decode_ids(&buffer[..buffer.len() - 1]).is_err());
972 }
973
974 #[test]
975 fn test_sparse_validator_matches_decoder() {
976 let codec = SparsePrimaryKeyCodec::schemaless();
977 let mut validator = SparsePrimaryKeyValidator::default();
978 let mut prefix = Vec::new();
979 codec.encode_internal(0, 0, &mut prefix).unwrap();
980 let mut cases = vec![prefix.clone()];
981 let mut max_prefix = Vec::new();
982 codec
983 .encode_internal(u32::MAX, u64::MAX, &mut max_prefix)
984 .unwrap();
985 cases.push(max_prefix);
986
987 for label in ["", "a", "12345678", "123456789", "1234567🦀末尾", "日本語"]
988 .into_iter()
989 .map(String::from)
990 .chain([
991 "a".repeat(128),
992 format!("{}🦀", "a".repeat(127)),
993 format!("🦀{}", "a".repeat(127)),
994 ])
995 {
996 let mut key = prefix.clone();
997 codec
998 .encode_raw_tag_value([(37, label.as_bytes())].into_iter(), &mut key)
999 .unwrap();
1000 assert!(validator.validate(&key).is_ok());
1001 cases.push(key);
1002 }
1003
1004 let mut labels = prefix.clone();
1006 labels.extend_from_slice(&12_u32.to_be_bytes());
1007 labels.push(0);
1008 codec
1009 .encode_raw_tag_value(
1010 [(999, b"unknown".as_slice()), (0, b"first".as_slice())].into_iter(),
1011 &mut labels,
1012 )
1013 .unwrap();
1014 assert!(validator.validate(&labels).is_ok());
1015 cases.push(labels.clone());
1016
1017 let mut padded = cases[3].clone();
1019 let padding_offset = padded.len() - 2;
1020 padded[padding_offset] = 0xff;
1021 assert!(codec.decode(&padded).is_ok());
1022 assert!(validator.validate(&padded).is_ok());
1023 cases.push(padded);
1024
1025 for id in [
1026 12,
1027 RESERVED_COLUMN_ID_TABLE_ID,
1028 RESERVED_COLUMN_ID_TSID,
1029 u32::MAX,
1030 ] {
1031 let mut invalid = labels.clone();
1032 invalid.extend_from_slice(&id.to_be_bytes());
1033 invalid.push(0);
1034 assert!(codec.decode(&invalid).is_err());
1035 assert!(validator.validate(&invalid).is_err());
1036 cases.push(invalid);
1037 }
1038 for label in [
1039 b"\xff".as_slice(),
1040 b"\xc0\xaf",
1041 b"\xed\xa0\x80",
1042 b"1234567\xf4\x90\x80\x80",
1043 ] {
1044 let mut invalid = prefix.clone();
1045 codec
1046 .encode_raw_tag_value([(37, label)].into_iter(), &mut invalid)
1047 .unwrap();
1048 assert!(codec.decode(&invalid).is_err());
1049 assert!(validator.validate(&invalid).is_err());
1050 cases.push(invalid);
1051 }
1052
1053 let mut compare = |bytes: &[u8]| {
1056 assert_eq!(
1057 validator.validate(bytes).is_ok(),
1058 codec.decode(bytes).is_ok(),
1059 "{bytes:02x?}"
1060 );
1061 };
1062 for key in cases {
1063 compare(&key);
1064 for end in 0..key.len() {
1065 compare(&key[..end]);
1066 }
1067 for offset in 0..key.len() {
1068 let mut mutated = key.clone();
1069 for byte in 0..=u8::MAX {
1070 mutated[offset] = byte;
1071 compare(&mutated);
1072 }
1073 }
1074 }
1075 }
1076
1077 #[test]
1078 fn test_sparse_validator_reuses_state_for_unordered_columns() {
1079 let codec = SparsePrimaryKeyCodec::schemaless();
1080 let mut validator = SparsePrimaryKeyValidator::default();
1081 for num_tags in [512, 32, 1] {
1082 let mut key = Vec::new();
1083 codec.encode_internal(0, 0, &mut key).unwrap();
1084 codec
1085 .encode_raw_tag_value(
1086 (0..num_tags).map(|index| (index * 17 % num_tags, "1234567🦀".as_bytes())),
1087 &mut key,
1088 )
1089 .unwrap();
1090 assert!(validator.validate(&key).is_ok());
1091
1092 let mut duplicate = key.clone();
1093 duplicate.extend_from_slice(&0_u32.to_be_bytes());
1094 duplicate.push(0);
1095 assert!(validator.validate(&duplicate).is_err());
1096 assert!(validator.validate(&key).is_ok());
1097 }
1098 }
1099
1100 #[test]
1101 fn test_has_column() {
1102 let region_metadata = test_region_metadata();
1103 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
1104 let mut buffer = Vec::new();
1105 let row = test_row();
1106 codec.encode_to_vec(row.into_iter(), &mut buffer).unwrap();
1107 assert!(!buffer.is_empty());
1108
1109 let mut offsets_map = SparseOffsetsCache::new();
1110 for column_id in [
1111 RESERVED_COLUMN_ID_TABLE_ID,
1112 RESERVED_COLUMN_ID_TSID,
1113 1,
1114 2,
1115 3,
1116 4,
1117 5,
1118 ] {
1119 let offset = codec.has_column(&buffer, &mut offsets_map, column_id);
1120 assert!(offset.is_some());
1121 }
1122
1123 let offset = codec.has_column(&buffer, &mut offsets_map, 6);
1124 assert!(offset.is_none());
1125 }
1126
1127 #[test]
1128 fn test_has_column_lazy_resume() {
1129 let region_metadata = test_region_metadata();
1130 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
1131 let mut buffer = Vec::new();
1132 codec
1133 .encode_to_vec(test_row().into_iter(), &mut buffer)
1134 .unwrap();
1135
1136 let mut cache = SparseOffsetsCache::new();
1137 assert!(codec.has_column(&buffer, &mut cache, 1).is_some());
1139 assert!(!cache.finished);
1140 assert!(cache.contains(1));
1141 assert!(!cache.contains(5));
1142
1143 assert!(codec.has_column(&buffer, &mut cache, 5).is_some());
1145 assert!(cache.contains(5));
1146
1147 assert!(codec.has_column(&buffer, &mut cache, 2).is_some());
1149
1150 assert!(codec.has_column(&buffer, &mut cache, 999).is_none());
1152 assert!(cache.finished);
1153 assert!(codec.has_column(&buffer, &mut cache, 998).is_none());
1155 }
1156
1157 #[test]
1158 fn test_decode_value_at() {
1159 let region_metadata = test_region_metadata();
1160 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
1161 let mut buffer = Vec::new();
1162 let row = test_row();
1163 codec.encode_to_vec(row.into_iter(), &mut buffer).unwrap();
1164 assert!(!buffer.is_empty());
1165
1166 let row = test_row();
1167 let mut offsets_map = SparseOffsetsCache::new();
1168 for column_id in [
1169 RESERVED_COLUMN_ID_TABLE_ID,
1170 RESERVED_COLUMN_ID_TSID,
1171 1,
1172 2,
1173 3,
1174 4,
1175 5,
1176 ] {
1177 let offset = codec
1178 .has_column(&buffer, &mut offsets_map, column_id)
1179 .unwrap();
1180 let value = codec.decode_value_at(&buffer, offset, column_id).unwrap();
1181 let expected_value = row
1182 .iter()
1183 .find(|(id, _)| *id == column_id)
1184 .unwrap()
1185 .1
1186 .clone();
1187 assert_eq!(value.as_value_ref(), expected_value);
1188 }
1189 }
1190
1191 #[test]
1192 fn test_encoded_value_for_column() {
1193 let region_metadata = test_region_metadata();
1194 let codec = SparsePrimaryKeyCodec::new(®ion_metadata);
1195 let mut buffer = Vec::new();
1196 let row = test_row();
1197 codec
1198 .encode_to_vec(row.clone().into_iter(), &mut buffer)
1199 .unwrap();
1200 assert!(!buffer.is_empty());
1201
1202 let mut offsets_map = SparseOffsetsCache::new();
1203 for column_id in [
1204 RESERVED_COLUMN_ID_TABLE_ID,
1205 RESERVED_COLUMN_ID_TSID,
1206 1,
1207 2,
1208 3,
1209 4,
1210 5,
1211 ] {
1212 let encoded_value = codec
1213 .encoded_value_for_column(&buffer, &mut offsets_map, column_id)
1214 .unwrap()
1215 .unwrap();
1216 let expected_value = row
1217 .iter()
1218 .find(|(id, _)| *id == column_id)
1219 .unwrap()
1220 .1
1221 .clone();
1222 let data_type = match column_id {
1223 RESERVED_COLUMN_ID_TABLE_ID => ConcreteDataType::uint32_datatype(),
1224 RESERVED_COLUMN_ID_TSID => ConcreteDataType::uint64_datatype(),
1225 _ => ConcreteDataType::string_datatype(),
1226 };
1227 let field = SortField::new(data_type);
1228 let mut expected_encoded = Vec::new();
1229 let mut serializer = Serializer::new(&mut expected_encoded);
1230 field.serialize(&mut serializer, &expected_value).unwrap();
1231 assert_eq!(encoded_value, expected_encoded.as_slice());
1232 }
1233
1234 for column_id in [6_u32, 7_u32, 999_u32] {
1235 let encoded_value = codec
1236 .encoded_value_for_column(&buffer, &mut offsets_map, column_id)
1237 .unwrap();
1238 assert!(encoded_value.is_none());
1239 }
1240 }
1241}