Skip to main content

mito2/memtable/
time_series.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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
70/// Initial vector builder capacity.
71const INITIAL_BUILDER_CAPACITY: usize = 4;
72
73/// Vector builder capacity.
74const 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
82/// Checks whether a string field builder that currently holds `current_len` bytes can
83/// additionally accommodate `space_needed` bytes of string data, given that the offset of a
84/// single Arrow string array is limited to `limit` (`i32::MAX` in production).
85///
86/// Returns:
87/// - `Ok(true)` if `current_len + space_needed <= limit`;
88/// - `Ok(false)` if `space_needed <= limit` but `current_len + space_needed > limit`, i.e.
89///   the current builder is too full but an empty builder could accommodate the batch (the
90///   caller may freeze the current builder and replay the batch onto an empty one);
91/// - `Err(InvalidBatchSnafu)` if the batch's string data alone (`space_needed`, or the fact
92///   that its total bytes cannot even be represented as `i32`) exceeds `limit`, i.e. the
93///   batch can never be accommodated by any builder.
94fn 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
108/// Scans all string fields of a batch and checks whether they can be accommodated.
109///
110/// Every string field is checked (no early return on `Ok(false)`) so that an intrinsic
111/// oversize in *any* field surfaces as an error even when an earlier field only overflows
112/// the current builder.
113///
114/// Returns:
115/// - `Ok(true)` if every string field fits into the current builders;
116/// - `Ok(false)` if no field is intrinsically oversized but at least one field only fits
117///   into an empty builder (the caller may freeze the current builder and replay the batch
118///   onto an empty one);
119/// - `Err(InvalidBatchSnafu)` if any single field's string data alone (`space_needed`, or
120///   the fact that its total bytes cannot even be represented as `i32`) exceeds `limit`,
121///   i.e. that field can never be accommodated by any builder.
122fn 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/// Builder to build [TimeSeriesMemtable].
164#[derive(Debug, Default)]
165pub struct TimeSeriesMemtableBuilder {
166    write_buffer_manager: Option<WriteBufferManagerRef>,
167    dedup: bool,
168    merge_mode: MergeMode,
169}
170
171impl TimeSeriesMemtableBuilder {
172    /// Creates a new builder with specific `write_buffer_manager`.
173    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        // Now if we can use simple bulk memtable, the input request is already
209        // a bulk write request and won't call this method.
210        false
211    }
212}
213
214/// Memtable implementation that groups rows by their primary key.
215pub 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    /// Total written rows in memtable. This also includes deleted and duplicated rows.
228    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(&region_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    /// Updates memtable stats.
258    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        // safety: timestamp of kv must be both present and a valid timestamp value.
290        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        // TODO(hl): this maybe inaccurate since for-iteration may return early.
329        // We may lift the primary key length check out of Memtable::write
330        // so that we can ensure writing to memtable will succeed.
331        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        // Default implementation fallback to row iteration.
350        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            // no rows ever written
418            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            // The map may be dropped while unwinding from a panic that poisoned a lock.
478            .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    /// Push [KeyValue] to SeriesSet with given primary key and return key/value allocated memory size.
509    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            // safety: series must exist at given index.
531            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    /// Iterates all series in [SeriesSet].
549    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
581/// Creates an arrow [SchemaRef](arrow::datatypes::SchemaRef) that only contains primary keys
582/// of given region schema
583pub(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/// Metrics for reading the memtable.
600#[derive(Debug, Default)]
601struct Metrics {
602    /// Total series in the memtable.
603    total_series: usize,
604    /// Number of series pruned.
605    num_pruned_series: usize,
606    /// Number of rows read.
607    num_rows: usize,
608    /// Number of batch read.
609    num_batches: usize,
610    /// Duration to scan the memtable.
611    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        // Report MemScanMetrics if not already reported
699        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        // TODO(hl): maybe yield more than one time series to amortize range overhead.
724        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                // read next series
739                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            // Update metrics.
757            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); // Explicitly drop the read lock
764        self.metrics.scan_cost += start.elapsed();
765
766        // Report MemScanMetrics before returning None
767        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    // no primary key, we simply return true.
782    if pk_schema.fields().is_empty() {
783        return true;
784    }
785
786    // retrieve primary key values from cache or decode from bytes.
787    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    // evaluate predicates against primary key values
800    let mut result = true;
801    for predicate in predicates {
802        // ignore predicates that are not referencing primary key columns
803        let Ok(index) = pk_schema.index_of(predicate.column_name()) else {
804            continue;
805        };
806        // Safety: arrow schema and datatypes are constructed from the same source.
807        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
816/// A `Series` holds a list of field values of some given primary key.
817pub 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    /// Pushes a row of values into Series. Return the size of values.
850    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        // + 10 to avoid potential reallocation.
858        if self.active.len() + 10 > self.capacity {
859            let region_metadata = self.region_metadata.clone();
860            self.freeze(&region_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    /// Freezes the active part and push it to `frozen`.
870    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(&region_metadata);
888        }
889        self.active.extend(ts_v, op_type_v, sequence_v, fields)
890    }
891
892    /// Freezes active part to frozen part and compact frozen part to reduce memory fragmentation.
893    /// Returns the frozen and compacted values.
894    pub(crate) fn compact(&mut self, region_metadata: &RegionMetadataRef) -> Result<&Values> {
895        self.freeze(region_metadata);
896
897        let frozen = &self.frozen;
898
899        // Each series must contain at least one row
900        debug_assert!(!frozen.is_empty());
901
902        if frozen.len() > 1 {
903            // TODO(hl): We should keep track of min/max timestamps for each values and avoid
904            // cloning and sorting when values do not overlap with each other.
905
906            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
941/// `ValueBuilder` holds all the vector builders for field columns.
942pub(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    /// Returns number of field builders.
977    pub fn num_field_builders(&self) -> usize {
978        self.fields.iter().flatten().count()
979    }
980
981    /// Pushes a new row to `ValueBuilder`.
982    /// We don't need primary keys since they've already be encoded.
983    /// Returns the size of field values.
984    ///
985    /// In this method, we don't check the data type of the value, because it is already checked in the caller.
986    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    /// Checks if current value builder have sufficient space to accommodate `fields`.
1032    ///
1033    /// Returns `Ok(false)` if the current builder lacks the remaining space to accommodate
1034    /// the fields due to offset overflow, but an empty builder would be able to accommodate
1035    /// the batch (the caller may freeze the current builder and replay the batch onto an
1036    /// empty one).
1037    ///
1038    /// Returns `Err(InvalidBatchSnafu)` if the string data of a single batch itself exceeds
1039    /// the Arrow string array offset limit and thus can never be accommodated, not even by an
1040    /// empty builder.
1041    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    /// Returns the length of [ValueBuilder]
1152    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/// [Values] holds an immutable vectors of field columns, including `sequence` and `op_type`.
1213#[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    /// Converts [Values] to `Batch`, applies the optional sequence filter, sorts the batch
1223    /// according to `timestamp, sequence` desc, and applies dedup/merge according to `merge_mode`.
1224    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        // The sequence filter must be applied before dedup/merge to:
1253        // - avoid dropping a timestamp when the newest row is out of range
1254        // - avoid filling null fields from rows that should be excluded by the sequence filter.
1255        batch.filter_by_sequence(sequence)?;
1256
1257        match (dedup, merge_mode) {
1258            // append-only, keep duplicate rows.
1259            (false, _) => batch.sort(false)?,
1260            // keep the last row for each timestamp.
1261            (true, MergeMode::LastRow) => batch.sort(true)?,
1262            // keep the last non-null value for each field.
1263            (true, MergeMode::LastNonNull) => {
1264                batch.sort(false)?;
1265                batch.merge_last_non_null()?;
1266            }
1267        }
1268        Ok(batch)
1269    }
1270
1271    /// Returns a vector of all columns converted to arrow [Array](datatypes::arrow::array::Array) in [Values].
1272    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    /// Builds a new [Values] instance from columns.
1282    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(&region_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(&region_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(&region_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(&region_metadata);
1535        // col1: NULL 1 2 3
1536        // col2: NULL NULL 10.2 NULL
1537        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(&region_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        // Same timestamp, newest sequence is out of range. We should still keep the timestamp by
1659        // using the latest row *within* the sequence range as the base row.
1660        //
1661        // Expect after filtering seq<=2:
1662        // - base row: seq=2
1663        // - v0 from seq=2, v1 filled from seq=1
1664        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        // Same timestamp, older sequence is out of range. We must not fill null fields using rows
1707        // that should be excluded by the sequence filter.
1708        //
1709        // Expect after filtering seq>1:
1710        // - keep only seq=2 row, v0 stays NULL.
1711        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        // Number of writer threads
2017        let num_writers = 10;
2018        // Number of reader threads
2019        let num_readers = 5;
2020        // Number of series per writer
2021        let series_per_writer = 100;
2022        // Number of rows per series
2023        let rows_per_series = 10;
2024        // Total number of series
2025        let total_series = num_writers * series_per_writer;
2026
2027        // Create a barrier to synchronize the start of all threads
2028        let barrier = Arc::new(std::sync::Barrier::new(num_writers + num_readers + 1));
2029
2030        // Spawn writer threads
2031        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                // Wait for all threads to be ready
2039                barrier.wait();
2040
2041                // Create and write series
2042                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        // Spawn reader threads
2054        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        // k0, k1 (pk columns), v0, v1 (field columns), ts, __primary_key, __sequence, __op_type
2126        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    /// Helper to create a TimeSeriesIterBuilder from a memtable and schema.
2189    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        // Project only field v0 (column_id=3) and ts (column_id=2).
2264        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        // Only projected columns + internal columns.
2285        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        // Write same data twice — dedup should keep only one copy per timestamp.
2321        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        // build_key_values creates a mutation with base sequence=0.
2354        // Each row gets sequence = base + row_index, so 5 rows get sequences 0,1,2,3,4.
2355        let kvs = build_key_values(&schema, "seq".to_string(), 1, 5);
2356        memtable.write(&kvs).unwrap();
2357
2358        // Filter to sequence > 4 — should yield no rows.
2359        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        // Filter to sequence <= 2 — should yield 3 rows (sequences 0, 1, 2).
2373        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        // Verify timestamp values.
2406        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        // Verify field v0 values.
2416        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        // Verify field v1 values.
2426        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        // Verify op_type is all Put (1).
2436        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        // A batch whose string data alone exceeds the Arrow string array offset limit can
2452        // never be accommodated, not even by an empty builder. `can_accommodate` must return
2453        // a structured `InvalidBatch` error instead of `Ok(false)`: the latter would make
2454        // `Series::extend` freeze the current builder and replay the same oversized batch
2455        // onto an empty builder, which then panics on offset overflow in `StringBuilder`.
2456        assert!(check_string_capacity(0, Some(101), 100).is_err());
2457        assert!(check_string_capacity(0, None, i32::MAX).is_err());
2458
2459        // A batch that fits in an empty builder but not in the current one reports
2460        // `Ok(false)` so the caller can freeze and replay onto an empty builder.
2461        assert!(!check_string_capacity(95, Some(10), 100).unwrap());
2462        assert!(!check_string_capacity(91, Some(10), 100).unwrap());
2463
2464        // The current builder can accommodate the batch when the combined size fits,
2465        // including the case where it exactly reaches the limit.
2466        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        // Two string fields: the first only overflows the *current* builder (an empty
2473        // builder would fit it), the second is intrinsically oversized. The scan must not
2474        // early-return `Ok(false)` on the first field: it has to check every string field so
2475        // the intrinsic oversize of the second field still surfaces as `InvalidBatch`.
2476        let limit = 10;
2477        // 8 bytes already in the current builder: 8 + 4 > 10, but 4 <= 10, so this field
2478        // alone fits an empty builder.
2479        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        // 15 bytes > limit: intrinsically oversized, can never fit any builder.
2489        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        // Sanity: without the oversized field the result is just `Ok(false)` (current full,
2501        // empty builder fits), which lets the caller freeze and replay onto an empty builder.
2502        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}