1use std::collections::btree_map::Entry;
16use std::collections::{BTreeMap, Bound, HashSet};
17use std::fmt::{Debug, Formatter};
18use std::iter;
19use std::sync::atomic::{AtomicI64, AtomicU64, AtomicUsize, Ordering};
20use std::sync::{Arc, PoisonError, RwLock};
21use std::time::{Duration, Instant};
22
23use api::v1::OpType;
24use common_recordbatch::filter::SimpleFilterEvaluator;
25use common_telemetry::{debug, error};
26use common_time::Timestamp;
27use datatypes::arrow;
28use datatypes::arrow::array::ArrayRef;
29use datatypes::arrow_array::StringArray;
30use datatypes::data_type::{ConcreteDataType, DataType};
31use datatypes::prelude::{ScalarVector, Vector, VectorRef};
32use datatypes::schema::ColumnSchema;
33use datatypes::types::TimestampType;
34use datatypes::value::{Value, ValueRef};
35use datatypes::vectors::{
36 Helper, StringVector, TimestampMicrosecondVector, TimestampMillisecondVector,
37 TimestampNanosecondVector, TimestampSecondVector, UInt8Vector, UInt64Vector,
38};
39use mito_codec::key_values::KeyValue;
40use mito_codec::row_converter::{DensePrimaryKeyCodec, PrimaryKeyCodecExt};
41use snafu::{OptionExt, ResultExt, ensure};
42use store_api::metadata::RegionMetadataRef;
43use store_api::storage::{ColumnId, SequenceNumber, SequenceRange};
44use table::predicate::Predicate;
45
46use crate::error::{
47 self, ComputeArrowSnafu, ConvertVectorSnafu, EncodeSnafu, PrimaryKeyLengthMismatchSnafu, Result,
48};
49use crate::flush::WriteBufferManagerRef;
50use crate::memtable::builder::FieldBuilder;
51use crate::memtable::bulk::part::BulkPart;
52use crate::memtable::simple_bulk_memtable::SimpleBulkMemtable;
53use crate::memtable::stats::WriteMetrics;
54use crate::memtable::{
55 AllocTracker, BatchToRecordBatchContext, BoxedBatchIterator, BoxedRecordBatchIterator,
56 IterBuilder, KeyValues, MemScanMetrics, Memtable, MemtableBuilder, MemtableId, MemtableRange,
57 MemtableRangeContext, MemtableRanges, MemtableRef, MemtableStats, RangesOptions,
58 read_column_ids_from_projection,
59};
60use crate::metrics::{
61 MEMTABLE_ACTIVE_FIELD_BUILDER_COUNT, MEMTABLE_ACTIVE_SERIES_COUNT, READ_ROWS_TOTAL,
62 READ_STAGE_ELAPSED,
63};
64use crate::read::dedup::LastNonNullIter;
65use crate::read::prune::PruneTimeIterator;
66use crate::read::scan_region::PredicateGroup;
67use crate::read::{Batch, BatchBuilder, BatchColumn};
68use crate::region::options::MergeMode;
69
70const INITIAL_BUILDER_CAPACITY: usize = 4;
72
73const BUILDER_CAPACITY: usize = 512;
75
76fn checked_string_values_size(mut lengths: impl Iterator<Item = usize>) -> Option<i32> {
77 lengths.try_fold(0_i32, |size, len| {
78 size.checked_add(i32::try_from(len).ok()?)
79 })
80}
81
82fn check_string_capacity(current_len: i32, space_needed: Option<i32>, limit: i32) -> Result<bool> {
95 let Some(space_needed) = space_needed.filter(|&space| space <= limit) else {
96 return error::InvalidBatchSnafu {
97 reason: format!(
98 "String data of the batch exceeds the Arrow string array offset limit ({limit}) and cannot be stored in a single column"
99 ),
100 }
101 .fail();
102 };
103 Ok(current_len
104 .checked_add(space_needed)
105 .is_some_and(|v| v <= limit))
106}
107
108fn scan_string_capacity(
123 fields: &[VectorRef],
124 field_builders: &[Option<FieldBuilder>],
125 field_types: &[ConcreteDataType],
126 limit: i32,
127) -> Result<bool> {
128 let mut can_fit_current = true;
129 for ((field_src, field_dest), field_type) in fields
130 .iter()
131 .zip(field_builders.iter())
132 .zip(field_types.iter())
133 {
134 if !matches!(field_type, ConcreteDataType::String(_)) {
135 continue;
136 }
137 let current_size = match field_dest {
138 Some(FieldBuilder::String(builder)) => builder.next_offset(),
139 None => 0,
140 Some(FieldBuilder::Other(_)) => unreachable!(),
141 };
142 let array = field_src.to_arrow_array();
143 let space_needed = if let Some(string_array) = array.as_any().downcast_ref::<StringArray>()
144 {
145 i32::try_from(string_array.value_data().len()).ok()
146 } else {
147 let string_vector = field_src
148 .as_any()
149 .downcast_ref::<StringVector>()
150 .with_context(|| error::InvalidBatchSnafu {
151 reason: format!(
152 "Field type mismatch, expecting String, given: {}",
153 field_src.data_type()
154 ),
155 })?;
156 checked_string_values_size(string_vector.iter_data().flatten().map(str::len))
157 };
158 can_fit_current &= check_string_capacity(current_size, space_needed, limit)?;
159 }
160 Ok(can_fit_current)
161}
162
163#[derive(Debug, Default)]
165pub struct TimeSeriesMemtableBuilder {
166 write_buffer_manager: Option<WriteBufferManagerRef>,
167 dedup: bool,
168 merge_mode: MergeMode,
169}
170
171impl TimeSeriesMemtableBuilder {
172 pub fn new(
174 write_buffer_manager: Option<WriteBufferManagerRef>,
175 dedup: bool,
176 merge_mode: MergeMode,
177 ) -> Self {
178 Self {
179 write_buffer_manager,
180 dedup,
181 merge_mode,
182 }
183 }
184}
185
186impl MemtableBuilder for TimeSeriesMemtableBuilder {
187 fn build(&self, id: MemtableId, metadata: &RegionMetadataRef) -> MemtableRef {
188 if metadata.primary_key.is_empty() {
189 Arc::new(SimpleBulkMemtable::new(
190 id,
191 metadata.clone(),
192 self.write_buffer_manager.clone(),
193 self.dedup,
194 self.merge_mode,
195 ))
196 } else {
197 Arc::new(TimeSeriesMemtable::new(
198 metadata.clone(),
199 id,
200 self.write_buffer_manager.clone(),
201 self.dedup,
202 self.merge_mode,
203 ))
204 }
205 }
206
207 fn use_bulk_insert(&self, _metadata: &RegionMetadataRef) -> bool {
208 false
211 }
212}
213
214pub struct TimeSeriesMemtable {
216 id: MemtableId,
217 region_metadata: RegionMetadataRef,
218 row_codec: Arc<DensePrimaryKeyCodec>,
219 series_set: SeriesSet,
220 alloc_tracker: AllocTracker,
221 max_timestamp: AtomicI64,
222 min_timestamp: AtomicI64,
223 max_sequence: AtomicU64,
224 min_sequence: AtomicU64,
225 dedup: bool,
226 merge_mode: MergeMode,
227 num_rows: AtomicUsize,
229}
230
231impl TimeSeriesMemtable {
232 pub fn new(
233 region_metadata: RegionMetadataRef,
234 id: MemtableId,
235 write_buffer_manager: Option<WriteBufferManagerRef>,
236 dedup: bool,
237 merge_mode: MergeMode,
238 ) -> Self {
239 let row_codec = Arc::new(DensePrimaryKeyCodec::new(®ion_metadata));
240 let series_set = SeriesSet::new(region_metadata.clone(), row_codec.clone());
241 Self {
242 id,
243 region_metadata,
244 series_set,
245 row_codec,
246 alloc_tracker: AllocTracker::new(write_buffer_manager),
247 max_timestamp: AtomicI64::new(i64::MIN),
248 min_timestamp: AtomicI64::new(i64::MAX),
249 max_sequence: AtomicU64::new(0),
250 min_sequence: AtomicU64::new(u64::MAX),
251 dedup,
252 merge_mode,
253 num_rows: Default::default(),
254 }
255 }
256
257 fn update_stats(&self, stats: WriteMetrics) {
259 self.alloc_tracker
260 .on_allocation(stats.key_bytes + stats.value_bytes);
261 self.max_timestamp.fetch_max(stats.max_ts, Ordering::SeqCst);
262 self.min_timestamp.fetch_min(stats.min_ts, Ordering::SeqCst);
263 self.max_sequence
264 .fetch_max(stats.max_sequence, Ordering::SeqCst);
265 self.min_sequence
266 .fetch_min(stats.min_sequence, Ordering::SeqCst);
267 self.num_rows.fetch_add(stats.num_rows, Ordering::SeqCst);
268 }
269
270 fn write_key_value(&self, kv: KeyValue, stats: &mut WriteMetrics) -> Result<()> {
271 ensure!(
272 self.row_codec.num_fields() == kv.num_primary_keys(),
273 PrimaryKeyLengthMismatchSnafu {
274 expect: self.row_codec.num_fields(),
275 actual: kv.num_primary_keys(),
276 }
277 );
278
279 let primary_key_encoded = self
280 .row_codec
281 .encode(kv.primary_keys())
282 .context(EncodeSnafu)?;
283
284 let (key_allocated, value_allocated) =
285 self.series_set.push_to_series(primary_key_encoded, &kv);
286 stats.key_bytes += key_allocated;
287 stats.value_bytes += value_allocated;
288
289 let ts = kv
291 .timestamp()
292 .try_into_timestamp()
293 .unwrap()
294 .unwrap()
295 .value();
296 stats.min_ts = stats.min_ts.min(ts);
297 stats.max_ts = stats.max_ts.max(ts);
298 stats.min_sequence = stats.min_sequence.min(kv.sequence());
299 Ok(())
300 }
301}
302
303impl Debug for TimeSeriesMemtable {
304 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
305 f.debug_struct("TimeSeriesMemtable").finish()
306 }
307}
308
309impl Memtable for TimeSeriesMemtable {
310 fn id(&self) -> MemtableId {
311 self.id
312 }
313
314 fn write(&self, kvs: &KeyValues) -> Result<()> {
315 if kvs.is_empty() {
316 return Ok(());
317 }
318
319 let mut local_stats = WriteMetrics::default();
320
321 for kv in kvs.iter() {
322 self.write_key_value(kv, &mut local_stats)?;
323 }
324 local_stats.value_bytes += kvs.num_rows() * std::mem::size_of::<Timestamp>();
325 local_stats.value_bytes += kvs.num_rows() * std::mem::size_of::<OpType>();
326 local_stats.max_sequence = kvs.max_sequence();
327 local_stats.num_rows = kvs.num_rows();
328 self.update_stats(local_stats);
332 Ok(())
333 }
334
335 fn write_one(&self, key_value: KeyValue) -> Result<()> {
336 let mut metrics = WriteMetrics::default();
337 let res = self.write_key_value(key_value, &mut metrics);
338 metrics.value_bytes += std::mem::size_of::<Timestamp>() + std::mem::size_of::<OpType>();
339 metrics.max_sequence = key_value.sequence();
340 metrics.num_rows = 1;
341
342 if res.is_ok() {
343 self.update_stats(metrics);
344 }
345 res
346 }
347
348 fn write_bulk(&self, part: BulkPart) -> Result<()> {
349 let mutation = part.to_mutation(&self.region_metadata)?;
351 let mut metrics = WriteMetrics::default();
352 if let Some(key_values) = KeyValues::new(&self.region_metadata, mutation) {
353 for kv in key_values.iter() {
354 self.write_key_value(kv, &mut metrics)?
355 }
356 }
357
358 metrics.max_sequence = part.sequence;
359 metrics.max_ts = part.max_timestamp;
360 metrics.min_ts = part.min_timestamp;
361 metrics.num_rows = part.num_rows();
362 self.update_stats(metrics);
363 Ok(())
364 }
365
366 fn ranges(
367 &self,
368 projection: Option<&[ColumnId]>,
369 options: RangesOptions,
370 ) -> Result<MemtableRanges> {
371 let predicate = options.predicate;
372 let sequence = options.sequence;
373 let read_column_ids = read_column_ids_from_projection(&self.region_metadata, projection);
374 let projection = if let Some(projection) = projection {
375 projection.iter().copied().collect()
376 } else {
377 self.region_metadata
378 .field_columns()
379 .map(|c| c.column_id)
380 .collect()
381 };
382 let batch_to_record_batch = Arc::new(BatchToRecordBatchContext::new(
383 self.region_metadata.clone(),
384 read_column_ids,
385 ));
386 let builder = Box::new(TimeSeriesIterBuilder {
387 series_set: self.series_set.clone(),
388 projection,
389 predicate: predicate.clone(),
390 dedup: self.dedup,
391 merge_mode: self.merge_mode,
392 sequence,
393 batch_to_record_batch,
394 });
395 let context = Arc::new(MemtableRangeContext::new(self.id, builder, predicate));
396 let range_stats = self.stats();
397 let range = MemtableRange::new(context, range_stats);
398 Ok(MemtableRanges {
399 ranges: [(0, range)].into(),
400 })
401 }
402
403 fn is_empty(&self) -> bool {
404 self.series_set.series.read().unwrap().0.is_empty()
405 }
406
407 fn freeze(&self) -> Result<()> {
408 self.alloc_tracker.done_allocating();
409
410 Ok(())
411 }
412
413 fn stats(&self) -> MemtableStats {
414 let estimated_bytes = self.alloc_tracker.bytes_allocated();
415
416 if estimated_bytes == 0 {
417 return MemtableStats {
419 estimated_bytes,
420 time_range: None,
421 num_rows: 0,
422 num_ranges: 0,
423 max_sequence: 0,
424 min_sequence: 0,
425 series_count: 0,
426 };
427 }
428 let ts_type = self
429 .region_metadata
430 .time_index_column()
431 .column_schema
432 .data_type
433 .clone()
434 .as_timestamp()
435 .expect("Timestamp column must have timestamp type");
436 let max_timestamp = ts_type.create_timestamp(self.max_timestamp.load(Ordering::Relaxed));
437 let min_timestamp = ts_type.create_timestamp(self.min_timestamp.load(Ordering::Relaxed));
438 let series_count = self.series_set.series.read().unwrap().0.len();
439 MemtableStats {
440 estimated_bytes,
441 time_range: Some((min_timestamp, max_timestamp)),
442 num_rows: self.num_rows.load(Ordering::Relaxed),
443 num_ranges: 1,
444 max_sequence: self.max_sequence.load(Ordering::Relaxed),
445 min_sequence: self.min_sequence.load(Ordering::Relaxed),
446 series_count,
447 }
448 }
449
450 fn min_sequence(&self) -> SequenceNumber {
451 if self.alloc_tracker.bytes_allocated() == 0 {
452 return 0;
453 }
454 self.min_sequence.load(Ordering::Relaxed)
455 }
456
457 fn fork(&self, id: MemtableId, metadata: &RegionMetadataRef) -> MemtableRef {
458 Arc::new(TimeSeriesMemtable::new(
459 metadata.clone(),
460 id,
461 self.alloc_tracker.write_buffer_manager(),
462 self.dedup,
463 self.merge_mode,
464 ))
465 }
466}
467
468#[derive(Default)]
469struct SeriesMap(BTreeMap<Vec<u8>, Arc<RwLock<Series>>>);
470
471impl Drop for SeriesMap {
472 fn drop(&mut self) {
473 let num_series = self.0.len();
474 let num_field_builders = self
475 .0
476 .values()
477 .map(|v| {
479 v.read()
480 .unwrap_or_else(PoisonError::into_inner)
481 .active
482 .num_field_builders()
483 })
484 .sum::<usize>();
485 MEMTABLE_ACTIVE_SERIES_COUNT.sub(num_series as i64);
486 MEMTABLE_ACTIVE_FIELD_BUILDER_COUNT.sub(num_field_builders as i64);
487 }
488}
489
490#[derive(Clone)]
491pub(crate) struct SeriesSet {
492 region_metadata: RegionMetadataRef,
493 series: Arc<RwLock<SeriesMap>>,
494 codec: Arc<DensePrimaryKeyCodec>,
495}
496
497impl SeriesSet {
498 fn new(region_metadata: RegionMetadataRef, codec: Arc<DensePrimaryKeyCodec>) -> Self {
499 Self {
500 region_metadata,
501 series: Default::default(),
502 codec,
503 }
504 }
505}
506
507impl SeriesSet {
508 fn push_to_series(&self, primary_key: Vec<u8>, kv: &KeyValue) -> (usize, usize) {
510 if let Some(series) = self.series.read().unwrap().0.get(&primary_key) {
511 let value_allocated = series.write().unwrap().push(
512 kv.timestamp(),
513 kv.sequence(),
514 kv.op_type(),
515 kv.fields(),
516 );
517 return (0, value_allocated);
518 };
519
520 let mut indices = self.series.write().unwrap();
521 match indices.0.entry(primary_key) {
522 Entry::Vacant(v) => {
523 let key_len = v.key().len();
524 let mut series = Series::new(&self.region_metadata);
525 let value_allocated =
526 series.push(kv.timestamp(), kv.sequence(), kv.op_type(), kv.fields());
527 v.insert(Arc::new(RwLock::new(series)));
528 (key_len, value_allocated)
529 }
530 Entry::Occupied(v) => {
532 let value_allocated = v.get().write().unwrap().push(
533 kv.timestamp(),
534 kv.sequence(),
535 kv.op_type(),
536 kv.fields(),
537 );
538 (0, value_allocated)
539 }
540 }
541 }
542
543 #[cfg(test)]
544 fn get_series(&self, primary_key: &[u8]) -> Option<Arc<RwLock<Series>>> {
545 self.series.read().unwrap().0.get(primary_key).cloned()
546 }
547
548 fn iter_series(
550 &self,
551 projection: HashSet<ColumnId>,
552 predicate: PredicateGroup,
553 dedup: bool,
554 merge_mode: MergeMode,
555 sequence: Option<SequenceRange>,
556 mem_scan_metrics: Option<MemScanMetrics>,
557 ) -> Result<Iter> {
558 let primary_key_schema = primary_key_schema(&self.region_metadata);
559 let primary_key_datatypes = self
560 .region_metadata
561 .primary_key_columns()
562 .map(|pk| pk.column_schema.data_type.clone())
563 .collect();
564
565 Iter::try_new(
566 self.region_metadata.clone(),
567 self.series.clone(),
568 projection,
569 predicate.predicate().cloned(),
570 primary_key_schema,
571 primary_key_datatypes,
572 self.codec.clone(),
573 dedup,
574 merge_mode,
575 sequence,
576 mem_scan_metrics,
577 )
578 }
579}
580
581pub(crate) fn primary_key_schema(
584 region_metadata: &RegionMetadataRef,
585) -> arrow::datatypes::SchemaRef {
586 let fields = region_metadata
587 .primary_key_columns()
588 .map(|pk| {
589 arrow::datatypes::Field::new(
590 pk.column_schema.name.clone(),
591 pk.column_schema.data_type.as_arrow_type(),
592 pk.column_schema.is_nullable(),
593 )
594 })
595 .collect::<Vec<_>>();
596 Arc::new(arrow::datatypes::Schema::new(fields))
597}
598
599#[derive(Debug, Default)]
601struct Metrics {
602 total_series: usize,
604 num_pruned_series: usize,
606 num_rows: usize,
608 num_batches: usize,
610 scan_cost: Duration,
612}
613
614struct Iter {
615 metadata: RegionMetadataRef,
616 series: Arc<RwLock<SeriesMap>>,
617 projection: HashSet<ColumnId>,
618 last_key: Option<Vec<u8>>,
619 predicate: Vec<SimpleFilterEvaluator>,
620 pk_schema: arrow::datatypes::SchemaRef,
621 pk_datatypes: Vec<ConcreteDataType>,
622 codec: Arc<DensePrimaryKeyCodec>,
623 dedup: bool,
624 merge_mode: MergeMode,
625 sequence: Option<SequenceRange>,
626 metrics: Metrics,
627 mem_scan_metrics: Option<MemScanMetrics>,
628}
629
630impl Iter {
631 #[allow(clippy::too_many_arguments)]
632 pub(crate) fn try_new(
633 metadata: RegionMetadataRef,
634 series: Arc<RwLock<SeriesMap>>,
635 projection: HashSet<ColumnId>,
636 predicate: Option<Predicate>,
637 pk_schema: arrow::datatypes::SchemaRef,
638 pk_datatypes: Vec<ConcreteDataType>,
639 codec: Arc<DensePrimaryKeyCodec>,
640 dedup: bool,
641 merge_mode: MergeMode,
642 sequence: Option<SequenceRange>,
643 mem_scan_metrics: Option<MemScanMetrics>,
644 ) -> Result<Self> {
645 let predicate = predicate
646 .map(|predicate| {
647 predicate
648 .exprs()
649 .iter()
650 .filter_map(|expr| {
651 SimpleFilterEvaluator::try_new_with_column_type(expr, &|name| {
652 metadata
653 .column_by_name(name)
654 .map(|column| column.column_schema.data_type.as_arrow_type())
655 })
656 })
657 .collect::<Vec<_>>()
658 })
659 .unwrap_or_default();
660 Ok(Self {
661 metadata,
662 series,
663 projection,
664 last_key: None,
665 predicate,
666 pk_schema,
667 pk_datatypes,
668 codec,
669 dedup,
670 merge_mode,
671 sequence,
672 metrics: Metrics::default(),
673 mem_scan_metrics,
674 })
675 }
676
677 fn report_mem_scan_metrics(&mut self) {
678 if let Some(mem_scan_metrics) = self.mem_scan_metrics.take() {
679 let inner = crate::memtable::MemScanMetricsData {
680 total_series: self.metrics.total_series,
681 num_rows: self.metrics.num_rows,
682 num_batches: self.metrics.num_batches,
683 scan_cost: self.metrics.scan_cost,
684 ..Default::default()
685 };
686 mem_scan_metrics.merge_inner(&inner);
687 }
688 }
689}
690
691impl Drop for Iter {
692 fn drop(&mut self) {
693 debug!(
694 "Iter {} time series memtable, metrics: {:?}",
695 self.metadata.region_id, self.metrics
696 );
697
698 self.report_mem_scan_metrics();
700
701 READ_ROWS_TOTAL
702 .with_label_values(&["time_series_memtable"])
703 .inc_by(self.metrics.num_rows as u64);
704 READ_STAGE_ELAPSED
705 .with_label_values(&["scan_memtable"])
706 .observe(self.metrics.scan_cost.as_secs_f64());
707 }
708}
709
710impl Iterator for Iter {
711 type Item = Result<Batch>;
712
713 fn next(&mut self) -> Option<Self::Item> {
714 let start = Instant::now();
715 let map = self.series.read().unwrap();
716 let range = match &self.last_key {
717 None => map.0.range::<Vec<u8>, _>(..),
718 Some(last_key) => map
719 .0
720 .range::<Vec<u8>, _>((Bound::Excluded(last_key), Bound::Unbounded)),
721 };
722
723 for (primary_key, series) in range {
725 self.metrics.total_series += 1;
726
727 let mut series = series.write().unwrap();
728 if !self.predicate.is_empty()
729 && !prune_primary_key(
730 &self.codec,
731 primary_key.as_slice(),
732 &mut series,
733 &self.pk_datatypes,
734 self.pk_schema.clone(),
735 &self.predicate,
736 )
737 {
738 self.metrics.num_pruned_series += 1;
740 continue;
741 }
742 self.last_key = Some(primary_key.clone());
743
744 let values = series.compact(&self.metadata);
745 let batch = values.and_then(|v| {
746 v.to_batch(
747 primary_key,
748 &self.metadata,
749 &self.projection,
750 self.sequence,
751 self.dedup,
752 self.merge_mode,
753 )
754 });
755
756 self.metrics.num_batches += 1;
758 self.metrics.num_rows += batch.as_ref().map(|b| b.num_rows()).unwrap_or(0);
759 self.metrics.scan_cost += start.elapsed();
760
761 return Some(batch);
762 }
763 drop(map); self.metrics.scan_cost += start.elapsed();
765
766 self.report_mem_scan_metrics();
768
769 None
770 }
771}
772
773fn prune_primary_key(
774 codec: &Arc<DensePrimaryKeyCodec>,
775 pk: &[u8],
776 series: &mut Series,
777 datatypes: &[ConcreteDataType],
778 pk_schema: arrow::datatypes::SchemaRef,
779 predicates: &[SimpleFilterEvaluator],
780) -> bool {
781 if pk_schema.fields().is_empty() {
783 return true;
784 }
785
786 let pk_values = if let Some(pk_values) = series.pk_cache.as_ref() {
788 pk_values
789 } else {
790 let pk_values = codec.decode_dense_without_column_id(pk);
791 if let Err(e) = pk_values {
792 error!(e; "Failed to decode primary key");
793 return true;
794 }
795 series.update_pk_cache(pk_values.unwrap());
796 series.pk_cache.as_ref().unwrap()
797 };
798
799 let mut result = true;
801 for predicate in predicates {
802 let Ok(index) = pk_schema.index_of(predicate.column_name()) else {
804 continue;
805 };
806 let scalar_value = pk_values[index]
808 .try_to_scalar_value(&datatypes[index])
809 .unwrap();
810 result &= predicate.evaluate_scalar(&scalar_value).unwrap_or(true);
811 }
812
813 result
814}
815
816pub struct Series {
818 pk_cache: Option<Vec<Value>>,
819 active: ValueBuilder,
820 frozen: Vec<Values>,
821 region_metadata: RegionMetadataRef,
822 capacity: usize,
823}
824
825impl Series {
826 pub(crate) fn with_capacity(
827 region_metadata: &RegionMetadataRef,
828 init_capacity: usize,
829 capacity: usize,
830 ) -> Self {
831 MEMTABLE_ACTIVE_SERIES_COUNT.inc();
832 Self {
833 pk_cache: None,
834 active: ValueBuilder::new(region_metadata, init_capacity),
835 frozen: vec![],
836 region_metadata: region_metadata.clone(),
837 capacity,
838 }
839 }
840
841 pub(crate) fn new(region_metadata: &RegionMetadataRef) -> Self {
842 Self::with_capacity(region_metadata, INITIAL_BUILDER_CAPACITY, BUILDER_CAPACITY)
843 }
844
845 pub fn is_empty(&self) -> bool {
846 self.active.len() == 0 && self.frozen.is_empty()
847 }
848
849 pub(crate) fn push<'a>(
851 &mut self,
852 ts: ValueRef<'a>,
853 sequence: u64,
854 op_type: OpType,
855 values: impl Iterator<Item = ValueRef<'a>>,
856 ) -> usize {
857 if self.active.len() + 10 > self.capacity {
859 let region_metadata = self.region_metadata.clone();
860 self.freeze(®ion_metadata);
861 }
862 self.active.push(ts, sequence, op_type as u8, values)
863 }
864
865 fn update_pk_cache(&mut self, pk_values: Vec<Value>) {
866 self.pk_cache = Some(pk_values);
867 }
868
869 pub(crate) fn freeze(&mut self, region_metadata: &RegionMetadataRef) {
871 if self.active.len() != 0 {
872 let mut builder = ValueBuilder::new(region_metadata, INITIAL_BUILDER_CAPACITY);
873 std::mem::swap(&mut self.active, &mut builder);
874 self.frozen.push(Values::from(builder));
875 }
876 }
877
878 pub(crate) fn extend(
879 &mut self,
880 ts_v: VectorRef,
881 op_type_v: u8,
882 sequence_v: u64,
883 fields: Vec<VectorRef>,
884 ) -> Result<()> {
885 if !self.active.can_accommodate(&fields)? {
886 let region_metadata = self.region_metadata.clone();
887 self.freeze(®ion_metadata);
888 }
889 self.active.extend(ts_v, op_type_v, sequence_v, fields)
890 }
891
892 pub(crate) fn compact(&mut self, region_metadata: &RegionMetadataRef) -> Result<&Values> {
895 self.freeze(region_metadata);
896
897 let frozen = &self.frozen;
898
899 debug_assert!(!frozen.is_empty());
901
902 if frozen.len() > 1 {
903 let column_size = frozen[0].fields.len() + 3;
907
908 if cfg!(debug_assertions) {
909 debug_assert!(
910 frozen
911 .iter()
912 .zip(frozen.iter().skip(1))
913 .all(|(prev, next)| { prev.fields.len() == next.fields.len() })
914 );
915 }
916
917 let arrays = frozen.iter().map(|v| v.columns()).collect::<Vec<_>>();
918 let concatenated = (0..column_size)
919 .map(|i| {
920 let to_concat = arrays.iter().map(|a| a[i].as_ref()).collect::<Vec<_>>();
921 arrow::compute::concat(&to_concat)
922 })
923 .collect::<std::result::Result<Vec<_>, _>>()
924 .context(ComputeArrowSnafu)?;
925
926 debug_assert_eq!(concatenated.len(), column_size);
927 let values = Values::from_columns(&concatenated)?;
928 self.frozen = vec![values];
929 };
930 Ok(&self.frozen[0])
931 }
932
933 pub fn read_to_values(&self) -> Vec<Values> {
934 let mut res = Vec::with_capacity(self.frozen.len() + 1);
935 res.extend(self.frozen.iter().cloned());
936 res.push(self.active.finish_cloned());
937 res
938 }
939}
940
941pub(crate) struct ValueBuilder {
943 timestamp: Vec<i64>,
944 timestamp_type: ConcreteDataType,
945 sequence: Vec<u64>,
946 op_type: Vec<u8>,
947 fields: Vec<Option<FieldBuilder>>,
948 field_schemas: Vec<ColumnSchema>,
949}
950
951impl ValueBuilder {
952 pub(crate) fn new(region_metadata: &RegionMetadataRef, capacity: usize) -> Self {
953 let timestamp_type = region_metadata
954 .time_index_column()
955 .column_schema
956 .data_type
957 .clone();
958 let sequence = Vec::with_capacity(capacity);
959 let op_type = Vec::with_capacity(capacity);
960
961 let field_schemas = region_metadata
962 .field_columns()
963 .map(|c| c.column_schema.clone())
964 .collect::<Vec<_>>();
965 let fields = (0..field_schemas.len()).map(|_| None).collect();
966 Self {
967 timestamp: Vec::with_capacity(capacity),
968 timestamp_type,
969 sequence,
970 op_type,
971 fields,
972 field_schemas,
973 }
974 }
975
976 pub fn num_field_builders(&self) -> usize {
978 self.fields.iter().flatten().count()
979 }
980
981 pub(crate) fn push<'a>(
987 &mut self,
988 ts: ValueRef,
989 sequence: u64,
990 op_type: u8,
991 fields: impl Iterator<Item = ValueRef<'a>>,
992 ) -> usize {
993 #[cfg(debug_assertions)]
994 let fields = {
995 let field_vec = fields.collect::<Vec<_>>();
996 debug_assert_eq!(field_vec.len(), self.fields.len());
997 field_vec.into_iter()
998 };
999
1000 self.timestamp
1001 .push(ts.try_into_timestamp().unwrap().unwrap().value());
1002 self.sequence.push(sequence);
1003 self.op_type.push(op_type);
1004 let num_rows = self.timestamp.len();
1005 let mut size = 0;
1006 for (idx, field_value) in fields.enumerate() {
1007 size += field_value.data_size();
1008 if !field_value.is_null() || self.fields[idx].is_some() {
1009 if let Some(field) = self.fields[idx].as_mut() {
1010 field
1011 .push(field_value)
1012 .unwrap_or_else(|e| panic!("Failed to push field value: {e:?}"));
1013 } else {
1014 let mut mutable_vector = FieldBuilder::create(
1015 &self.field_schemas[idx],
1016 num_rows.max(INITIAL_BUILDER_CAPACITY),
1017 );
1018 mutable_vector.push_nulls(num_rows - 1);
1019 mutable_vector
1020 .push(field_value)
1021 .unwrap_or_else(|e| panic!("unexpected field value: {e:?}"));
1022 self.fields[idx] = Some(mutable_vector);
1023 MEMTABLE_ACTIVE_FIELD_BUILDER_COUNT.inc();
1024 }
1025 }
1026 }
1027
1028 size
1029 }
1030
1031 pub(crate) fn can_accommodate(&self, fields: &[VectorRef]) -> Result<bool> {
1042 let data_types = self
1043 .field_schemas
1044 .iter()
1045 .map(|x| x.data_type.clone())
1046 .collect::<Vec<_>>();
1047 scan_string_capacity(fields, &self.fields, &data_types, i32::MAX)
1048 }
1049
1050 pub(crate) fn extend(
1051 &mut self,
1052 ts_v: VectorRef,
1053 op_type: u8,
1054 sequence: u64,
1055 fields: Vec<VectorRef>,
1056 ) -> Result<()> {
1057 let num_rows_before = self.timestamp.len();
1058 let num_rows_to_write = ts_v.len();
1059 self.timestamp.reserve(num_rows_to_write);
1060 match self.timestamp_type {
1061 ConcreteDataType::Timestamp(TimestampType::Second(_)) => {
1062 self.timestamp.extend(
1063 ts_v.as_any()
1064 .downcast_ref::<TimestampSecondVector>()
1065 .unwrap()
1066 .iter_data()
1067 .map(|v| v.unwrap().0.value()),
1068 );
1069 }
1070 ConcreteDataType::Timestamp(TimestampType::Millisecond(_)) => {
1071 self.timestamp.extend(
1072 ts_v.as_any()
1073 .downcast_ref::<TimestampMillisecondVector>()
1074 .unwrap()
1075 .iter_data()
1076 .map(|v| v.unwrap().0.value()),
1077 );
1078 }
1079 ConcreteDataType::Timestamp(TimestampType::Microsecond(_)) => {
1080 self.timestamp.extend(
1081 ts_v.as_any()
1082 .downcast_ref::<TimestampMicrosecondVector>()
1083 .unwrap()
1084 .iter_data()
1085 .map(|v| v.unwrap().0.value()),
1086 );
1087 }
1088 ConcreteDataType::Timestamp(TimestampType::Nanosecond(_)) => {
1089 self.timestamp.extend(
1090 ts_v.as_any()
1091 .downcast_ref::<TimestampNanosecondVector>()
1092 .unwrap()
1093 .iter_data()
1094 .map(|v| v.unwrap().0.value()),
1095 );
1096 }
1097 _ => unreachable!(),
1098 };
1099
1100 self.op_type.reserve(num_rows_to_write);
1101 self.op_type
1102 .extend(iter::repeat_n(op_type, num_rows_to_write));
1103 self.sequence.reserve(num_rows_to_write);
1104 self.sequence
1105 .extend(iter::repeat_n(sequence, num_rows_to_write));
1106
1107 for (field_idx, (field_src, field_dest)) in
1108 fields.into_iter().zip(self.fields.iter_mut()).enumerate()
1109 {
1110 let builder = field_dest.get_or_insert_with(|| {
1111 let mut field_builder =
1112 FieldBuilder::create(&self.field_schemas[field_idx], INITIAL_BUILDER_CAPACITY);
1113 field_builder.push_nulls(num_rows_before);
1114 field_builder
1115 });
1116 match builder {
1117 FieldBuilder::String(builder) => {
1118 let array = field_src.to_arrow_array();
1119 if let Some(string_array) = array.as_any().downcast_ref::<StringArray>() {
1120 builder.append_array(string_array);
1121 } else {
1122 let string_vector = field_src
1123 .as_any()
1124 .downcast_ref::<StringVector>()
1125 .with_context(|| error::InvalidBatchSnafu {
1126 reason: format!(
1127 "Field type mismatch, expecting String, given: {}",
1128 field_src.data_type()
1129 ),
1130 })?;
1131 for value in string_vector.iter_data() {
1132 if let Some(value) = value {
1133 builder.append(value);
1134 } else {
1135 builder.append_null();
1136 }
1137 }
1138 }
1139 }
1140 FieldBuilder::Other(builder) => {
1141 let len = field_src.len();
1142 builder
1143 .extend_slice_of(&*field_src, 0, len)
1144 .context(error::ComputeVectorSnafu)?;
1145 }
1146 }
1147 }
1148 Ok(())
1149 }
1150
1151 fn len(&self) -> usize {
1153 let sequence_len = self.sequence.len();
1154 debug_assert_eq!(sequence_len, self.op_type.len());
1155 debug_assert_eq!(sequence_len, self.timestamp.len());
1156 sequence_len
1157 }
1158
1159 fn finish_cloned(&self) -> Values {
1160 let num_rows = self.sequence.len();
1161 let fields = self
1162 .fields
1163 .iter()
1164 .enumerate()
1165 .map(|(i, v)| {
1166 if let Some(v) = v {
1167 MEMTABLE_ACTIVE_FIELD_BUILDER_COUNT.dec();
1168 v.finish_cloned()
1169 } else {
1170 let mut builder = FieldBuilder::create(&self.field_schemas[i], num_rows);
1171 builder.push_nulls(num_rows);
1172 builder.finish()
1173 }
1174 })
1175 .collect::<Vec<_>>();
1176
1177 let sequence = Arc::new(UInt64Vector::from_vec(self.sequence.clone()));
1178 let op_type = Arc::new(UInt8Vector::from_vec(self.op_type.clone()));
1179 let timestamp: VectorRef = match self.timestamp_type {
1180 ConcreteDataType::Timestamp(TimestampType::Second(_)) => {
1181 Arc::new(TimestampSecondVector::from_vec(self.timestamp.clone()))
1182 }
1183 ConcreteDataType::Timestamp(TimestampType::Millisecond(_)) => {
1184 Arc::new(TimestampMillisecondVector::from_vec(self.timestamp.clone()))
1185 }
1186 ConcreteDataType::Timestamp(TimestampType::Microsecond(_)) => {
1187 Arc::new(TimestampMicrosecondVector::from_vec(self.timestamp.clone()))
1188 }
1189 ConcreteDataType::Timestamp(TimestampType::Nanosecond(_)) => {
1190 Arc::new(TimestampNanosecondVector::from_vec(self.timestamp.clone()))
1191 }
1192 _ => unreachable!(),
1193 };
1194
1195 if cfg!(debug_assertions) {
1196 debug_assert_eq!(timestamp.len(), sequence.len());
1197 debug_assert_eq!(timestamp.len(), op_type.len());
1198 for field in &fields {
1199 debug_assert_eq!(timestamp.len(), field.len());
1200 }
1201 }
1202
1203 Values {
1204 timestamp,
1205 sequence,
1206 op_type,
1207 fields,
1208 }
1209 }
1210}
1211
1212#[derive(Clone)]
1214pub struct Values {
1215 pub(crate) timestamp: VectorRef,
1216 pub(crate) sequence: Arc<UInt64Vector>,
1217 pub(crate) op_type: Arc<UInt8Vector>,
1218 pub(crate) fields: Vec<VectorRef>,
1219}
1220
1221impl Values {
1222 pub fn to_batch(
1225 &self,
1226 primary_key: &[u8],
1227 metadata: &RegionMetadataRef,
1228 projection: &HashSet<ColumnId>,
1229 sequence: Option<SequenceRange>,
1230 dedup: bool,
1231 merge_mode: MergeMode,
1232 ) -> Result<Batch> {
1233 let builder = BatchBuilder::with_required_columns(
1234 primary_key.to_vec(),
1235 self.timestamp.clone(),
1236 self.sequence.clone(),
1237 self.op_type.clone(),
1238 );
1239
1240 let fields = metadata
1241 .field_columns()
1242 .zip(self.fields.iter())
1243 .filter_map(|(c, f)| {
1244 projection.get(&c.column_id).map(|c| BatchColumn {
1245 column_id: *c,
1246 data: f.clone(),
1247 })
1248 })
1249 .collect();
1250
1251 let mut batch = builder.with_fields(fields).build()?;
1252 batch.filter_by_sequence(sequence)?;
1256
1257 match (dedup, merge_mode) {
1258 (false, _) => batch.sort(false)?,
1260 (true, MergeMode::LastRow) => batch.sort(true)?,
1262 (true, MergeMode::LastNonNull) => {
1264 batch.sort(false)?;
1265 batch.merge_last_non_null()?;
1266 }
1267 }
1268 Ok(batch)
1269 }
1270
1271 fn columns(&self) -> Vec<ArrayRef> {
1273 let mut res = Vec::with_capacity(3 + self.fields.len());
1274 res.push(self.timestamp.to_arrow_array());
1275 res.push(self.sequence.to_arrow_array());
1276 res.push(self.op_type.to_arrow_array());
1277 res.extend(self.fields.iter().map(|f| f.to_arrow_array()));
1278 res
1279 }
1280
1281 fn from_columns(cols: &[ArrayRef]) -> Result<Self> {
1283 debug_assert!(cols.len() >= 3);
1284 let timestamp = Helper::try_into_vector(&cols[0]).context(ConvertVectorSnafu)?;
1285 let sequence =
1286 Arc::new(UInt64Vector::try_from_arrow_array(&cols[1]).context(ConvertVectorSnafu)?);
1287 let op_type =
1288 Arc::new(UInt8Vector::try_from_arrow_array(&cols[2]).context(ConvertVectorSnafu)?);
1289 let fields = Helper::try_into_vectors(&cols[3..]).context(ConvertVectorSnafu)?;
1290
1291 Ok(Self {
1292 timestamp,
1293 sequence,
1294 op_type,
1295 fields,
1296 })
1297 }
1298}
1299
1300impl From<ValueBuilder> for Values {
1301 fn from(mut value: ValueBuilder) -> Self {
1302 let num_rows = value.len();
1303 let fields = value
1304 .fields
1305 .iter_mut()
1306 .enumerate()
1307 .map(|(i, v)| {
1308 if let Some(v) = v {
1309 MEMTABLE_ACTIVE_FIELD_BUILDER_COUNT.dec();
1310 v.finish()
1311 } else {
1312 let mut builder = FieldBuilder::create(&value.field_schemas[i], num_rows);
1313 builder.push_nulls(num_rows);
1314 builder.finish()
1315 }
1316 })
1317 .collect::<Vec<_>>();
1318
1319 let sequence = Arc::new(UInt64Vector::from_vec(value.sequence));
1320 let op_type = Arc::new(UInt8Vector::from_vec(value.op_type));
1321 let timestamp: VectorRef = match value.timestamp_type {
1322 ConcreteDataType::Timestamp(TimestampType::Second(_)) => {
1323 Arc::new(TimestampSecondVector::from_vec(value.timestamp))
1324 }
1325 ConcreteDataType::Timestamp(TimestampType::Millisecond(_)) => {
1326 Arc::new(TimestampMillisecondVector::from_vec(value.timestamp))
1327 }
1328 ConcreteDataType::Timestamp(TimestampType::Microsecond(_)) => {
1329 Arc::new(TimestampMicrosecondVector::from_vec(value.timestamp))
1330 }
1331 ConcreteDataType::Timestamp(TimestampType::Nanosecond(_)) => {
1332 Arc::new(TimestampNanosecondVector::from_vec(value.timestamp))
1333 }
1334 _ => unreachable!(),
1335 };
1336
1337 if cfg!(debug_assertions) {
1338 debug_assert_eq!(timestamp.len(), sequence.len());
1339 debug_assert_eq!(timestamp.len(), op_type.len());
1340 for field in &fields {
1341 debug_assert_eq!(timestamp.len(), field.len());
1342 }
1343 }
1344
1345 Self {
1346 timestamp,
1347 sequence,
1348 op_type,
1349 fields,
1350 }
1351 }
1352}
1353
1354struct TimeSeriesIterBuilder {
1355 series_set: SeriesSet,
1356 projection: HashSet<ColumnId>,
1357 predicate: PredicateGroup,
1358 dedup: bool,
1359 sequence: Option<SequenceRange>,
1360 merge_mode: MergeMode,
1361 batch_to_record_batch: Arc<BatchToRecordBatchContext>,
1362}
1363
1364impl IterBuilder for TimeSeriesIterBuilder {
1365 fn build(&self, metrics: Option<MemScanMetrics>) -> Result<BoxedBatchIterator> {
1366 let iter = self.series_set.iter_series(
1367 self.projection.clone(),
1368 self.predicate.clone(),
1369 self.dedup,
1370 self.merge_mode,
1371 self.sequence,
1372 metrics,
1373 )?;
1374 if self.merge_mode == MergeMode::LastNonNull {
1375 let iter = LastNonNullIter::new(iter);
1376 Ok(Box::new(iter))
1377 } else {
1378 Ok(Box::new(iter))
1379 }
1380 }
1381
1382 fn is_record_batch(&self) -> bool {
1383 true
1384 }
1385
1386 fn build_record_batch(
1387 &self,
1388 time_range: Option<(Timestamp, Timestamp)>,
1389 metrics: Option<MemScanMetrics>,
1390 ) -> Result<BoxedRecordBatchIterator> {
1391 let iter = self.build(metrics)?;
1392 let iter: BoxedBatchIterator = if let Some(time_range) = time_range {
1393 let time_filters = self.predicate.time_filters();
1394 Box::new(PruneTimeIterator::new(iter, time_range, time_filters))
1395 } else {
1396 iter
1397 };
1398 Ok(self.batch_to_record_batch.adapt_iter(iter))
1399 }
1400}
1401
1402#[cfg(test)]
1403mod tests {
1404 use std::collections::{HashMap, HashSet};
1405
1406 use api::helper::ColumnDataTypeWrapper;
1407 use api::v1::helper::row;
1408 use api::v1::value::ValueData;
1409 use api::v1::{Mutation, Rows, SemanticType};
1410 use common_time::Timestamp;
1411 use datatypes::prelude::{ConcreteDataType, ScalarVector};
1412 use datatypes::schema::ColumnSchema;
1413 use datatypes::value::{OrderedFloat, Value};
1414 use datatypes::vectors::{Float64Vector, Int64Vector, TimestampMillisecondVector};
1415 use mito_codec::row_converter::SortField;
1416 use store_api::metadata::{ColumnMetadata, RegionMetadataBuilder};
1417 use store_api::storage::RegionId;
1418
1419 use super::*;
1420 use crate::memtable::builder::StringBuilder;
1421 use crate::test_util::column_metadata_to_column_schema;
1422
1423 fn schema_for_test() -> RegionMetadataRef {
1424 let mut builder = RegionMetadataBuilder::new(RegionId::new(123, 456));
1425 builder
1426 .push_column_metadata(ColumnMetadata {
1427 column_schema: ColumnSchema::new("k0", ConcreteDataType::string_datatype(), false),
1428 semantic_type: SemanticType::Tag,
1429 column_id: 0,
1430 })
1431 .push_column_metadata(ColumnMetadata {
1432 column_schema: ColumnSchema::new("k1", ConcreteDataType::int64_datatype(), false),
1433 semantic_type: SemanticType::Tag,
1434 column_id: 1,
1435 })
1436 .push_column_metadata(ColumnMetadata {
1437 column_schema: ColumnSchema::new(
1438 "ts",
1439 ConcreteDataType::timestamp_millisecond_datatype(),
1440 false,
1441 ),
1442 semantic_type: SemanticType::Timestamp,
1443 column_id: 2,
1444 })
1445 .push_column_metadata(ColumnMetadata {
1446 column_schema: ColumnSchema::new("v0", ConcreteDataType::int64_datatype(), true),
1447 semantic_type: SemanticType::Field,
1448 column_id: 3,
1449 })
1450 .push_column_metadata(ColumnMetadata {
1451 column_schema: ColumnSchema::new("v1", ConcreteDataType::float64_datatype(), true),
1452 semantic_type: SemanticType::Field,
1453 column_id: 4,
1454 })
1455 .primary_key(vec![0, 1]);
1456 let region_metadata = builder.build().unwrap();
1457 Arc::new(region_metadata)
1458 }
1459
1460 fn ts_value_ref(val: i64) -> ValueRef<'static> {
1461 ValueRef::Timestamp(Timestamp::new_millisecond(val))
1462 }
1463
1464 fn field_value_ref(v0: i64, v1: f64) -> impl Iterator<Item = ValueRef<'static>> {
1465 vec![ValueRef::Int64(v0), ValueRef::Float64(OrderedFloat(v1))].into_iter()
1466 }
1467
1468 fn check_values(values: &Values, expect: &[(i64, u64, u8, i64, f64)]) {
1469 let ts = values
1470 .timestamp
1471 .as_any()
1472 .downcast_ref::<TimestampMillisecondVector>()
1473 .unwrap();
1474
1475 let v0 = values.fields[0]
1476 .as_any()
1477 .downcast_ref::<Int64Vector>()
1478 .unwrap();
1479 let v1 = values.fields[1]
1480 .as_any()
1481 .downcast_ref::<Float64Vector>()
1482 .unwrap();
1483 let read = ts
1484 .iter_data()
1485 .zip(values.sequence.iter_data())
1486 .zip(values.op_type.iter_data())
1487 .zip(v0.iter_data())
1488 .zip(v1.iter_data())
1489 .map(|((((ts, sequence), op_type), v0), v1)| {
1490 (
1491 ts.unwrap().0.value(),
1492 sequence.unwrap(),
1493 op_type.unwrap(),
1494 v0.unwrap(),
1495 v1.unwrap(),
1496 )
1497 })
1498 .collect::<Vec<_>>();
1499 assert_eq!(expect, &read);
1500 }
1501
1502 #[test]
1503 fn test_series_map_drop_with_poisoned_lock() {
1504 let region_metadata = schema_for_test();
1505 let series = Arc::new(RwLock::new(Series::new(®ion_metadata)));
1506 let map = SeriesMap(BTreeMap::from([(vec![1], series.clone())]));
1507 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1508 let _guard = series.write().unwrap();
1509 panic!("poison the series lock");
1510 }))
1511 .unwrap_err();
1512 assert!(series.is_poisoned());
1513 drop(map);
1514 }
1515
1516 #[test]
1517 fn test_series() {
1518 let region_metadata = schema_for_test();
1519 let mut series = Series::new(®ion_metadata);
1520 series.push(ts_value_ref(1), 0, OpType::Put, field_value_ref(1, 10.1));
1521 series.push(ts_value_ref(2), 0, OpType::Put, field_value_ref(2, 10.2));
1522 assert_eq!(2, series.active.timestamp.len());
1523 assert_eq!(0, series.frozen.len());
1524
1525 let values = series.compact(®ion_metadata).unwrap();
1526 check_values(values, &[(1, 0, 1, 1, 10.1), (2, 0, 1, 2, 10.2)]);
1527 assert_eq!(0, series.active.timestamp.len());
1528 assert_eq!(1, series.frozen.len());
1529 }
1530
1531 #[test]
1532 fn test_series_with_nulls() {
1533 let region_metadata = schema_for_test();
1534 let mut series = Series::new(®ion_metadata);
1535 series.push(
1538 ts_value_ref(1),
1539 0,
1540 OpType::Put,
1541 vec![ValueRef::Null, ValueRef::Null].into_iter(),
1542 );
1543 series.push(
1544 ts_value_ref(1),
1545 0,
1546 OpType::Put,
1547 vec![ValueRef::Int64(1), ValueRef::Null].into_iter(),
1548 );
1549 series.push(ts_value_ref(1), 2, OpType::Put, field_value_ref(2, 10.2));
1550 series.push(
1551 ts_value_ref(1),
1552 3,
1553 OpType::Put,
1554 vec![ValueRef::Int64(2), ValueRef::Null].into_iter(),
1555 );
1556 assert_eq!(4, series.active.timestamp.len());
1557 assert_eq!(0, series.frozen.len());
1558
1559 let values = series.compact(®ion_metadata).unwrap();
1560 assert_eq!(values.fields[0].null_count(), 1);
1561 assert_eq!(values.fields[1].null_count(), 3);
1562 assert_eq!(0, series.active.timestamp.len());
1563 assert_eq!(1, series.frozen.len());
1564 }
1565
1566 fn check_value(batch: &Batch, expect: Vec<Vec<Value>>) {
1567 let ts_len = batch.timestamps().len();
1568 assert_eq!(batch.sequences().len(), ts_len);
1569 assert_eq!(batch.op_types().len(), ts_len);
1570 for f in batch.fields() {
1571 assert_eq!(f.data.len(), ts_len);
1572 }
1573
1574 let mut rows = vec![];
1575 for idx in 0..ts_len {
1576 let mut row = Vec::with_capacity(batch.fields().len() + 3);
1577 row.push(batch.timestamps().get(idx));
1578 row.push(batch.sequences().get(idx));
1579 row.push(batch.op_types().get(idx));
1580 row.extend(batch.fields().iter().map(|f| f.data.get(idx)));
1581 rows.push(row);
1582 }
1583
1584 assert_eq!(expect.len(), rows.len());
1585 for (idx, row) in rows.iter().enumerate() {
1586 assert_eq!(&expect[idx], row);
1587 }
1588 }
1589
1590 #[test]
1591 fn test_values_sort() {
1592 let schema = schema_for_test();
1593 let timestamp = Arc::new(TimestampMillisecondVector::from_vec(vec![1, 2, 3, 4, 3]));
1594 let sequence = Arc::new(UInt64Vector::from_vec(vec![1, 1, 1, 1, 2]));
1595 let op_type = Arc::new(UInt8Vector::from_vec(vec![1, 1, 1, 1, 0]));
1596
1597 let fields = vec![
1598 Arc::new(Int64Vector::from_vec(vec![4, 3, 2, 1, 2])) as Arc<_>,
1599 Arc::new(Float64Vector::from_vec(vec![1.1, 2.1, 4.2, 3.3, 4.2])) as Arc<_>,
1600 ];
1601 let values = Values {
1602 timestamp: timestamp as Arc<_>,
1603 sequence,
1604 op_type,
1605 fields,
1606 };
1607
1608 let batch = values
1609 .to_batch(
1610 b"test",
1611 &schema,
1612 &[0, 1, 2, 3, 4].into_iter().collect(),
1613 None,
1614 true,
1615 MergeMode::LastRow,
1616 )
1617 .unwrap();
1618 check_value(
1619 &batch,
1620 vec![
1621 vec![
1622 Value::Timestamp(Timestamp::new_millisecond(1)),
1623 Value::UInt64(1),
1624 Value::UInt8(1),
1625 Value::Int64(4),
1626 Value::Float64(OrderedFloat(1.1)),
1627 ],
1628 vec![
1629 Value::Timestamp(Timestamp::new_millisecond(2)),
1630 Value::UInt64(1),
1631 Value::UInt8(1),
1632 Value::Int64(3),
1633 Value::Float64(OrderedFloat(2.1)),
1634 ],
1635 vec![
1636 Value::Timestamp(Timestamp::new_millisecond(3)),
1637 Value::UInt64(2),
1638 Value::UInt8(0),
1639 Value::Int64(2),
1640 Value::Float64(OrderedFloat(4.2)),
1641 ],
1642 vec![
1643 Value::Timestamp(Timestamp::new_millisecond(4)),
1644 Value::UInt64(1),
1645 Value::UInt8(1),
1646 Value::Int64(1),
1647 Value::Float64(OrderedFloat(3.3)),
1648 ],
1649 ],
1650 )
1651 }
1652
1653 #[test]
1654 fn test_last_non_null_should_filter_by_sequence_before_merge_drop_ts() {
1655 let schema = schema_for_test();
1656 let projection: HashSet<_> = [0, 1, 2, 3, 4].into_iter().collect();
1657
1658 let timestamp = Arc::new(TimestampMillisecondVector::from_vec(vec![1, 1, 1]));
1665 let sequence = Arc::new(UInt64Vector::from_vec(vec![1, 2, 3]));
1666 let op_type = Arc::new(UInt8Vector::from_vec(vec![OpType::Put as u8; 3]));
1667 let fields = vec![
1668 Arc::new(Int64Vector::from(vec![None, Some(10), None])) as Arc<_>,
1669 Arc::new(Float64Vector::from(vec![Some(1.5), None, None])) as Arc<_>,
1670 ];
1671 let values = Values {
1672 timestamp: timestamp as Arc<_>,
1673 sequence,
1674 op_type,
1675 fields,
1676 };
1677
1678 let batch = values
1679 .to_batch(
1680 b"test",
1681 &schema,
1682 &projection,
1683 Some(SequenceRange::LtEq { max: 2 }),
1684 true,
1685 MergeMode::LastNonNull,
1686 )
1687 .unwrap();
1688
1689 check_value(
1690 &batch,
1691 vec![vec![
1692 Value::Timestamp(Timestamp::new_millisecond(1)),
1693 Value::UInt64(2),
1694 Value::UInt8(OpType::Put as u8),
1695 Value::Int64(10),
1696 Value::Float64(OrderedFloat(1.5)),
1697 ]],
1698 );
1699 }
1700
1701 #[test]
1702 fn test_last_non_null_should_filter_by_sequence_before_merge_no_fill_from_out_of_range_row() {
1703 let schema = schema_for_test();
1704 let projection: HashSet<_> = [0, 1, 2, 3, 4].into_iter().collect();
1705
1706 let timestamp = Arc::new(TimestampMillisecondVector::from_vec(vec![1, 1]));
1712 let sequence = Arc::new(UInt64Vector::from_vec(vec![1, 2]));
1713 let op_type = Arc::new(UInt8Vector::from_vec(vec![OpType::Put as u8; 2]));
1714 let fields = vec![
1715 Arc::new(Int64Vector::from(vec![Some(10), None])) as Arc<_>,
1716 Arc::new(Float64Vector::from(vec![Some(1.0), Some(1.0)])) as Arc<_>,
1717 ];
1718 let values = Values {
1719 timestamp: timestamp as Arc<_>,
1720 sequence,
1721 op_type,
1722 fields,
1723 };
1724
1725 let batch = values
1726 .to_batch(
1727 b"test",
1728 &schema,
1729 &projection,
1730 Some(SequenceRange::Gt { min: 1 }),
1731 true,
1732 MergeMode::LastNonNull,
1733 )
1734 .unwrap();
1735
1736 check_value(
1737 &batch,
1738 vec![vec![
1739 Value::Timestamp(Timestamp::new_millisecond(1)),
1740 Value::UInt64(2),
1741 Value::UInt8(OpType::Put as u8),
1742 Value::Null,
1743 Value::Float64(OrderedFloat(1.0)),
1744 ]],
1745 );
1746 }
1747
1748 fn build_key_values(schema: &RegionMetadataRef, k0: String, k1: i64, len: usize) -> KeyValues {
1749 let column_schema = schema
1750 .column_metadatas
1751 .iter()
1752 .map(|c| api::v1::ColumnSchema {
1753 column_name: c.column_schema.name.clone(),
1754 datatype: ColumnDataTypeWrapper::try_from(c.column_schema.data_type.clone())
1755 .unwrap()
1756 .datatype() as i32,
1757 semantic_type: c.semantic_type as i32,
1758 ..Default::default()
1759 })
1760 .collect();
1761
1762 let rows = (0..len)
1763 .map(|i| {
1764 row(vec![
1765 ValueData::StringValue(k0.clone()),
1766 ValueData::I64Value(k1),
1767 ValueData::TimestampMillisecondValue(i as i64),
1768 ValueData::I64Value(i as i64),
1769 ValueData::F64Value(i as f64),
1770 ])
1771 })
1772 .collect();
1773 let mutation = api::v1::Mutation {
1774 op_type: 1,
1775 sequence: 0,
1776 rows: Some(Rows {
1777 schema: column_schema,
1778 rows,
1779 }),
1780 write_hint: None,
1781 };
1782 KeyValues::new(schema.as_ref(), mutation).unwrap()
1783 }
1784
1785 #[test]
1786 fn test_min_sequence_covers_single_and_batch_writes_and_fork() {
1787 let schema = schema_for_test();
1788 let memtable =
1789 TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastNonNull);
1790 let kvs = build_key_values(&schema, "a".to_string(), 1, 5);
1791 assert_eq!(0, memtable.min_sequence());
1792 for sequence in [4, 2] {
1793 memtable
1794 .write_one(kvs.iter().nth(sequence).unwrap())
1795 .unwrap();
1796 assert_eq!(sequence as u64, memtable.stats().min_sequence);
1797 assert_eq!(sequence as u64, memtable.min_sequence());
1798 }
1799 memtable.write(&kvs).unwrap();
1800 assert_eq!(0, memtable.stats().min_sequence);
1801 assert_eq!(0, memtable.min_sequence());
1802 assert_eq!(4, memtable.stats().max_sequence);
1803 let fork = memtable.fork(2, &schema);
1804 assert!(fork.is_empty());
1805 assert_eq!(0, fork.min_sequence());
1806 fork.write_one(kvs.iter().nth(3).unwrap()).unwrap();
1807 assert_eq!(3, fork.stats().min_sequence);
1808 assert_eq!(3, fork.min_sequence());
1809 }
1810
1811 #[test]
1812 fn test_series_set_concurrency() {
1813 let schema = schema_for_test();
1814 let row_codec = Arc::new(DensePrimaryKeyCodec::with_fields(
1815 schema
1816 .primary_key_columns()
1817 .map(|c| {
1818 (
1819 c.column_id,
1820 SortField::new(c.column_schema.data_type.clone()),
1821 )
1822 })
1823 .collect(),
1824 ));
1825 let set = Arc::new(SeriesSet::new(schema.clone(), row_codec));
1826
1827 let concurrency = 32;
1828 let pk_num = concurrency * 2;
1829 let mut handles = Vec::with_capacity(concurrency);
1830 for i in 0..concurrency {
1831 let set = set.clone();
1832 let schema = schema.clone();
1833 let column_schemas = schema
1834 .column_metadatas
1835 .iter()
1836 .map(column_metadata_to_column_schema)
1837 .collect::<Vec<_>>();
1838 let handle = std::thread::spawn(move || {
1839 for j in i * 100..(i + 1) * 100 {
1840 let pk = j % pk_num;
1841 let primary_key = format!("pk-{}", pk).as_bytes().to_vec();
1842
1843 let kvs = KeyValues::new(
1844 &schema,
1845 Mutation {
1846 op_type: OpType::Put as i32,
1847 sequence: j as u64,
1848 rows: Some(Rows {
1849 schema: column_schemas.clone(),
1850 rows: vec![row(vec![
1851 ValueData::StringValue(format!("{}", j)),
1852 ValueData::I64Value(j as i64),
1853 ValueData::TimestampMillisecondValue(j as i64),
1854 ValueData::I64Value(j as i64),
1855 ValueData::F64Value(j as f64),
1856 ])],
1857 }),
1858 write_hint: None,
1859 },
1860 )
1861 .unwrap();
1862 set.push_to_series(primary_key, &kvs.iter().next().unwrap());
1863 }
1864 });
1865 handles.push(handle);
1866 }
1867 for h in handles {
1868 h.join().unwrap();
1869 }
1870
1871 let mut timestamps = Vec::with_capacity(concurrency * 100);
1872 let mut sequences = Vec::with_capacity(concurrency * 100);
1873 let mut op_types = Vec::with_capacity(concurrency * 100);
1874 let mut v0 = Vec::with_capacity(concurrency * 100);
1875
1876 for i in 0..pk_num {
1877 let pk = format!("pk-{}", i).as_bytes().to_vec();
1878 let series = set.get_series(&pk).unwrap();
1879 let mut guard = series.write().unwrap();
1880 let values = guard.compact(&schema).unwrap();
1881 timestamps.extend(values.sequence.iter_data().map(|v| v.unwrap() as i64));
1882 sequences.extend(values.sequence.iter_data().map(|v| v.unwrap() as i64));
1883 op_types.extend(values.op_type.iter_data().map(|v| v.unwrap()));
1884 v0.extend(
1885 values
1886 .fields
1887 .first()
1888 .unwrap()
1889 .as_any()
1890 .downcast_ref::<Int64Vector>()
1891 .unwrap()
1892 .iter_data()
1893 .map(|v| v.unwrap()),
1894 );
1895 }
1896
1897 let expected_sequence = (0..(concurrency * 100) as i64).collect::<HashSet<_>>();
1898 assert_eq!(
1899 expected_sequence,
1900 sequences.iter().copied().collect::<HashSet<_>>()
1901 );
1902
1903 op_types.iter().all(|op| *op == OpType::Put as u8);
1904 assert_eq!(
1905 expected_sequence,
1906 timestamps.iter().copied().collect::<HashSet<_>>()
1907 );
1908
1909 assert_eq!(timestamps, sequences);
1910 assert_eq!(v0, timestamps);
1911 }
1912
1913 #[test]
1914 fn test_memtable() {
1915 common_telemetry::init_default_ut_logging();
1916 check_memtable_dedup(true);
1917 check_memtable_dedup(false);
1918 }
1919
1920 fn check_memtable_dedup(dedup: bool) {
1921 let schema = schema_for_test();
1922 let kvs = build_key_values(&schema, "hello".to_string(), 42, 100);
1923 let memtable = TimeSeriesMemtable::new(schema, 42, None, dedup, MergeMode::LastRow);
1924 memtable.write(&kvs).unwrap();
1925 memtable.write(&kvs).unwrap();
1926
1927 let mut expected_ts: HashMap<i64, usize> = HashMap::new();
1928 for ts in kvs.iter().map(|kv| {
1929 kv.timestamp()
1930 .try_into_timestamp()
1931 .unwrap()
1932 .unwrap()
1933 .value()
1934 }) {
1935 *expected_ts.entry(ts).or_default() += if dedup { 1 } else { 2 };
1936 }
1937
1938 let ranges = memtable.ranges(None, RangesOptions::default()).unwrap();
1939 let range = ranges.ranges.into_values().next().unwrap();
1940 let iter = range.build_iter().unwrap();
1941 let mut read = HashMap::new();
1942
1943 for ts in iter
1944 .flat_map(|batch| {
1945 batch
1946 .unwrap()
1947 .timestamps()
1948 .as_any()
1949 .downcast_ref::<TimestampMillisecondVector>()
1950 .unwrap()
1951 .iter_data()
1952 .collect::<Vec<_>>()
1953 .into_iter()
1954 })
1955 .map(|v| v.unwrap().0.value())
1956 {
1957 *read.entry(ts).or_default() += 1;
1958 }
1959 assert_eq!(expected_ts, read);
1960
1961 let stats = memtable.stats();
1962 assert!(stats.bytes_allocated() > 0);
1963 assert_eq!(
1964 Some((
1965 Timestamp::new_millisecond(0),
1966 Timestamp::new_millisecond(99)
1967 )),
1968 stats.time_range()
1969 );
1970 }
1971
1972 #[test]
1973 fn test_memtable_projection() {
1974 common_telemetry::init_default_ut_logging();
1975 let schema = schema_for_test();
1976 let kvs = build_key_values(&schema, "hello".to_string(), 42, 100);
1977 let memtable = TimeSeriesMemtable::new(schema, 42, None, true, MergeMode::LastRow);
1978 memtable.write(&kvs).unwrap();
1979
1980 let iter = memtable
1981 .ranges(Some(&[3]), RangesOptions::default())
1982 .unwrap()
1983 .build(None)
1984 .unwrap();
1985
1986 let mut v0_all = vec![];
1987
1988 for res in iter {
1989 let batch = res.unwrap();
1990 assert_eq!(1, batch.fields().len());
1991 let v0 = batch
1992 .fields()
1993 .first()
1994 .unwrap()
1995 .data
1996 .as_any()
1997 .downcast_ref::<Int64Vector>()
1998 .unwrap();
1999 v0_all.extend(v0.iter_data().map(|v| v.unwrap()));
2000 }
2001 assert_eq!((0..100i64).collect::<Vec<_>>(), v0_all);
2002 }
2003
2004 #[test]
2005 fn test_memtable_concurrent_write_read() {
2006 common_telemetry::init_default_ut_logging();
2007 let schema = schema_for_test();
2008 let memtable = Arc::new(TimeSeriesMemtable::new(
2009 schema.clone(),
2010 42,
2011 None,
2012 true,
2013 MergeMode::LastRow,
2014 ));
2015
2016 let num_writers = 10;
2018 let num_readers = 5;
2020 let series_per_writer = 100;
2022 let rows_per_series = 10;
2024 let total_series = num_writers * series_per_writer;
2026
2027 let barrier = Arc::new(std::sync::Barrier::new(num_writers + num_readers + 1));
2029
2030 let mut writer_handles = Vec::with_capacity(num_writers);
2032 for writer_id in 0..num_writers {
2033 let memtable = memtable.clone();
2034 let schema = schema.clone();
2035 let barrier = barrier.clone();
2036
2037 let handle = std::thread::spawn(move || {
2038 barrier.wait();
2040
2041 for series_id in 0..series_per_writer {
2043 let series_key = format!("writer-{}-series-{}", writer_id, series_id);
2044 let kvs =
2045 build_key_values(&schema, series_key, series_id as i64, rows_per_series);
2046 memtable.write(&kvs).unwrap();
2047 }
2048 });
2049
2050 writer_handles.push(handle);
2051 }
2052
2053 let mut reader_handles = Vec::with_capacity(num_readers);
2055 for _ in 0..num_readers {
2056 let memtable = memtable.clone();
2057 let barrier = barrier.clone();
2058
2059 let handle = std::thread::spawn(move || {
2060 barrier.wait();
2061
2062 for _ in 0..10 {
2063 let iter = memtable
2064 .ranges(None, RangesOptions::default())
2065 .unwrap()
2066 .build(None)
2067 .unwrap();
2068 for batch_result in iter {
2069 let _ = batch_result.unwrap();
2070 }
2071 }
2072 });
2073
2074 reader_handles.push(handle);
2075 }
2076
2077 barrier.wait();
2078
2079 for handle in writer_handles {
2080 handle.join().unwrap();
2081 }
2082 for handle in reader_handles {
2083 handle.join().unwrap();
2084 }
2085
2086 let iter = memtable
2087 .ranges(None, RangesOptions::default())
2088 .unwrap()
2089 .build(None)
2090 .unwrap();
2091 let mut series_count = 0;
2092 let mut row_count = 0;
2093
2094 for batch_result in iter {
2095 let batch = batch_result.unwrap();
2096 series_count += 1;
2097 row_count += batch.num_rows();
2098 }
2099 assert_eq!(total_series, series_count);
2100 assert_eq!(total_series * rows_per_series, row_count);
2101 }
2102
2103 #[test]
2104 fn test_build_record_batch_iter_from_memtable() {
2105 let schema = schema_for_test();
2106 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2107
2108 let kvs = build_key_values(&schema, "test".to_string(), 1, 10);
2109 memtable.write(&kvs).unwrap();
2110
2111 let read_column_ids: Vec<ColumnId> = schema
2112 .column_metadatas
2113 .iter()
2114 .map(|c| c.column_id)
2115 .collect();
2116 let ranges = memtable
2117 .ranges(Some(&read_column_ids), RangesOptions::default())
2118 .unwrap();
2119 assert_eq!(1, ranges.ranges.len());
2120
2121 let range = ranges.ranges.into_values().next().unwrap();
2122 let mut iter = range.build_record_batch_iter(None, None).unwrap();
2123 let rb = iter.next().transpose().unwrap().unwrap();
2124 assert_eq!(10, rb.num_rows());
2125 let schema = rb.schema();
2127 let column_names: Vec<_> = schema.fields().iter().map(|f| f.name().as_str()).collect();
2128 assert_eq!(
2129 column_names,
2130 vec![
2131 "k0",
2132 "k1",
2133 "v0",
2134 "v1",
2135 "ts",
2136 "__primary_key",
2137 "__sequence",
2138 "__op_type",
2139 ]
2140 );
2141 assert!(iter.next().is_none());
2142 }
2143
2144 #[test]
2145 fn test_build_record_batch_iter_with_time_range() {
2146 let schema = schema_for_test();
2147 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2148
2149 let kvs = build_key_values(&schema, "test".to_string(), 1, 10);
2150 memtable.write(&kvs).unwrap();
2151
2152 let read_column_ids: Vec<ColumnId> = schema
2153 .column_metadatas
2154 .iter()
2155 .map(|c| c.column_id)
2156 .collect();
2157 let ranges = memtable
2158 .ranges(Some(&read_column_ids), RangesOptions::default())
2159 .unwrap();
2160 assert_eq!(1, ranges.ranges.len());
2161
2162 let time_range = (Timestamp::new_millisecond(3), Timestamp::new_millisecond(7));
2163
2164 let range = ranges.ranges.into_values().next().unwrap();
2165 let mut iter = range
2166 .build_record_batch_iter(Some(time_range), None)
2167 .unwrap();
2168
2169 let mut total_rows = 0;
2170 let mut all_timestamps = Vec::new();
2171 while let Some(rb) = iter.next().transpose().unwrap() {
2172 total_rows += rb.num_rows();
2173 let ts_col = rb
2174 .column_by_name("ts")
2175 .unwrap()
2176 .as_any()
2177 .downcast_ref::<datatypes::arrow::array::TimestampMillisecondArray>()
2178 .unwrap();
2179 for i in 0..ts_col.len() {
2180 all_timestamps.push(ts_col.value(i));
2181 }
2182 }
2183 assert_eq!(5, total_rows);
2184 all_timestamps.sort();
2185 assert_eq!(vec![3, 4, 5, 6, 7], all_timestamps);
2186 }
2187
2188 fn build_iter_builder(
2190 schema: &RegionMetadataRef,
2191 memtable: &TimeSeriesMemtable,
2192 projection: Option<&[ColumnId]>,
2193 dedup: bool,
2194 merge_mode: MergeMode,
2195 sequence: Option<SequenceRange>,
2196 ) -> TimeSeriesIterBuilder {
2197 let read_column_ids = read_column_ids_from_projection(schema, projection);
2198 let field_projection = if let Some(projection) = projection {
2199 projection.iter().copied().collect()
2200 } else {
2201 schema.field_columns().map(|c| c.column_id).collect()
2202 };
2203 let adapter_context = Arc::new(BatchToRecordBatchContext::new(
2204 schema.clone(),
2205 read_column_ids,
2206 ));
2207 TimeSeriesIterBuilder {
2208 series_set: memtable.series_set.clone(),
2209 projection: field_projection,
2210 predicate: PredicateGroup::default(),
2211 dedup,
2212 merge_mode,
2213 sequence,
2214 batch_to_record_batch: adapter_context,
2215 }
2216 }
2217
2218 #[test]
2219 fn test_iter_builder_build_record_batch_basic() {
2220 let schema = schema_for_test();
2221 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2222
2223 let kvs = build_key_values(&schema, "hello".to_string(), 42, 10);
2224 memtable.write(&kvs).unwrap();
2225
2226 let builder = build_iter_builder(&schema, &memtable, None, true, MergeMode::LastRow, None);
2227
2228 let mut iter = builder.build_record_batch(None, None).unwrap();
2229 let rb = iter.next().transpose().unwrap().unwrap();
2230 assert_eq!(10, rb.num_rows());
2231
2232 let rb_schema = rb.schema();
2233 let col_names: Vec<_> = rb_schema
2234 .fields()
2235 .iter()
2236 .map(|f| f.name().as_str())
2237 .collect();
2238 assert_eq!(
2239 col_names,
2240 vec![
2241 "k0",
2242 "k1",
2243 "v0",
2244 "v1",
2245 "ts",
2246 "__primary_key",
2247 "__sequence",
2248 "__op_type",
2249 ]
2250 );
2251
2252 assert!(iter.next().is_none());
2253 }
2254
2255 #[test]
2256 fn test_iter_builder_build_record_batch_with_projection() {
2257 let schema = schema_for_test();
2258 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2259
2260 let kvs = build_key_values(&schema, "test".to_string(), 1, 5);
2261 memtable.write(&kvs).unwrap();
2262
2263 let projection = vec![2, 3];
2265 let builder = build_iter_builder(
2266 &schema,
2267 &memtable,
2268 Some(&projection),
2269 true,
2270 MergeMode::LastRow,
2271 None,
2272 );
2273
2274 let mut iter = builder.build_record_batch(None, None).unwrap();
2275 let rb = iter.next().transpose().unwrap().unwrap();
2276 assert_eq!(5, rb.num_rows());
2277
2278 let rb_schema = rb.schema();
2279 let col_names: Vec<_> = rb_schema
2280 .fields()
2281 .iter()
2282 .map(|f| f.name().as_str())
2283 .collect();
2284 assert_eq!(
2286 col_names,
2287 vec!["v0", "ts", "__primary_key", "__sequence", "__op_type",]
2288 );
2289
2290 assert!(iter.next().is_none());
2291 }
2292
2293 #[test]
2294 fn test_iter_builder_build_record_batch_multiple_series() {
2295 let schema = schema_for_test();
2296 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2297
2298 let kvs_a = build_key_values(&schema, "aaa".to_string(), 1, 3);
2299 let kvs_b = build_key_values(&schema, "bbb".to_string(), 2, 4);
2300 memtable.write(&kvs_a).unwrap();
2301 memtable.write(&kvs_b).unwrap();
2302
2303 let builder = build_iter_builder(&schema, &memtable, None, true, MergeMode::LastRow, None);
2304
2305 let iter = builder.build_record_batch(None, None).unwrap();
2306 let mut total_rows = 0;
2307 for rb in iter {
2308 let rb = rb.unwrap();
2309 total_rows += rb.num_rows();
2310 assert_eq!(8, rb.num_columns());
2311 }
2312 assert_eq!(7, total_rows);
2313 }
2314
2315 #[test]
2316 fn test_iter_builder_build_record_batch_dedup() {
2317 let schema = schema_for_test();
2318 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2319
2320 let kvs = build_key_values(&schema, "dup".to_string(), 10, 5);
2322 memtable.write(&kvs).unwrap();
2323 memtable.write(&kvs).unwrap();
2324
2325 let builder = build_iter_builder(&schema, &memtable, None, true, MergeMode::LastRow, None);
2326
2327 let iter = builder.build_record_batch(None, None).unwrap();
2328 let total_rows: usize = iter.map(|rb| rb.unwrap().num_rows()).sum();
2329 assert_eq!(5, total_rows);
2330 }
2331
2332 #[test]
2333 fn test_iter_builder_build_record_batch_no_dedup() {
2334 let schema = schema_for_test();
2335 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, false, MergeMode::LastRow);
2336
2337 let kvs = build_key_values(&schema, "dup".to_string(), 10, 5);
2338 memtable.write(&kvs).unwrap();
2339 memtable.write(&kvs).unwrap();
2340
2341 let builder = build_iter_builder(&schema, &memtable, None, false, MergeMode::LastRow, None);
2342
2343 let iter = builder.build_record_batch(None, None).unwrap();
2344 let total_rows: usize = iter.map(|rb| rb.unwrap().num_rows()).sum();
2345 assert_eq!(10, total_rows);
2346 }
2347
2348 #[test]
2349 fn test_iter_builder_build_record_batch_with_sequence_filter() {
2350 let schema = schema_for_test();
2351 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2352
2353 let kvs = build_key_values(&schema, "seq".to_string(), 1, 5);
2356 memtable.write(&kvs).unwrap();
2357
2358 let builder = build_iter_builder(
2360 &schema,
2361 &memtable,
2362 None,
2363 true,
2364 MergeMode::LastRow,
2365 Some(SequenceRange::Gt { min: 4 }),
2366 );
2367
2368 let iter = builder.build_record_batch(None, None).unwrap();
2369 let total_rows: usize = iter.map(|rb| rb.unwrap().num_rows()).sum();
2370 assert_eq!(0, total_rows);
2371
2372 let builder = build_iter_builder(
2374 &schema,
2375 &memtable,
2376 None,
2377 true,
2378 MergeMode::LastRow,
2379 Some(SequenceRange::LtEq { max: 2 }),
2380 );
2381
2382 let iter = builder.build_record_batch(None, None).unwrap();
2383 let total_rows: usize = iter.map(|rb| rb.unwrap().num_rows()).sum();
2384 assert_eq!(3, total_rows);
2385 }
2386
2387 #[test]
2388 fn test_iter_builder_build_record_batch_data_correctness() {
2389 use datatypes::arrow::array::{
2390 Float64Array, Int64Array, TimestampMillisecondArray, UInt8Array,
2391 };
2392
2393 let schema = schema_for_test();
2394 let memtable = TimeSeriesMemtable::new(schema.clone(), 1, None, true, MergeMode::LastRow);
2395
2396 let kvs = build_key_values(&schema, "check".to_string(), 7, 3);
2397 memtable.write(&kvs).unwrap();
2398
2399 let builder = build_iter_builder(&schema, &memtable, None, true, MergeMode::LastRow, None);
2400
2401 let mut iter = builder.build_record_batch(None, None).unwrap();
2402 let rb = iter.next().transpose().unwrap().unwrap();
2403 assert_eq!(3, rb.num_rows());
2404
2405 let ts_col = rb
2407 .column_by_name("ts")
2408 .unwrap()
2409 .as_any()
2410 .downcast_ref::<TimestampMillisecondArray>()
2411 .unwrap();
2412 let timestamps: Vec<_> = (0..ts_col.len()).map(|i| ts_col.value(i)).collect();
2413 assert_eq!(vec![0, 1, 2], timestamps);
2414
2415 let v0_col = rb
2417 .column_by_name("v0")
2418 .unwrap()
2419 .as_any()
2420 .downcast_ref::<Int64Array>()
2421 .unwrap();
2422 let v0_values: Vec<_> = (0..v0_col.len()).map(|i| v0_col.value(i)).collect();
2423 assert_eq!(vec![0, 1, 2], v0_values);
2424
2425 let v1_col = rb
2427 .column_by_name("v1")
2428 .unwrap()
2429 .as_any()
2430 .downcast_ref::<Float64Array>()
2431 .unwrap();
2432 let v1_values: Vec<_> = (0..v1_col.len()).map(|i| v1_col.value(i)).collect();
2433 assert_eq!(vec![0.0, 1.0, 2.0], v1_values);
2434
2435 let op_col = rb
2437 .column_by_name("__op_type")
2438 .unwrap()
2439 .as_any()
2440 .downcast_ref::<UInt8Array>()
2441 .unwrap();
2442 for i in 0..op_col.len() {
2443 assert_eq!(OpType::Put as u8, op_col.value(i));
2444 }
2445
2446 assert!(iter.next().is_none());
2447 }
2448
2449 #[test]
2450 fn test_can_accommodate_string_offset_overflow() {
2451 assert!(check_string_capacity(0, Some(101), 100).is_err());
2457 assert!(check_string_capacity(0, None, i32::MAX).is_err());
2458
2459 assert!(!check_string_capacity(95, Some(10), 100).unwrap());
2462 assert!(!check_string_capacity(91, Some(10), 100).unwrap());
2463
2464 assert!(check_string_capacity(0, Some(100), 100).unwrap());
2467 assert!(check_string_capacity(90, Some(10), 100).unwrap());
2468 }
2469
2470 #[test]
2471 fn test_can_accommodate_checks_all_string_fields() {
2472 let limit = 10;
2477 let mut current = StringBuilder::with_capacity(1, 8);
2480 current.append("12345678");
2481 let field_builders = [Some(FieldBuilder::String(current)), None];
2482 let field_types = [
2483 ConcreteDataType::string_datatype(),
2484 ConcreteDataType::string_datatype(),
2485 ];
2486
2487 let first = Arc::new(StringVector::from(StringArray::from(vec!["abcd"]))) as VectorRef;
2488 let second = Arc::new(StringVector::from(StringArray::from(vec![
2490 "123456789012345",
2491 ]))) as VectorRef;
2492
2493 let err = scan_string_capacity(&[first, second], &field_builders, &field_types, limit)
2494 .unwrap_err();
2495 assert!(
2496 matches!(err, error::Error::InvalidBatch { .. }),
2497 "expected InvalidBatch, got {err:?}"
2498 );
2499
2500 let first_only = Arc::new(StringVector::from(StringArray::from(vec!["abcd"]))) as VectorRef;
2503 assert!(
2504 !scan_string_capacity(&[first_only], &field_builders, &field_types, limit).unwrap()
2505 );
2506 }
2507}