1use std::collections::{BTreeMap, HashMap};
16use std::marker::PhantomData;
17use std::ops::Bound;
18use std::ops::Bound::*;
19use std::sync::Arc;
20use std::time::Instant;
21
22use anyhow::anyhow;
23use await_tree::InstrumentAwait;
24use bytes::Bytes;
25use educe::Educe;
26use either::Either;
27use foyer::Hint;
28use futures::future::{ready, try_join_all};
29use futures::stream::BoxStream;
30use futures::{Stream, StreamExt, TryStreamExt, pin_mut};
31use itertools::Itertools;
32use risingwave_common::array::stream_record::Record;
33use risingwave_common::array::{ArrayImplBuilder, ArrayRef, DataChunk, Op, StreamChunk};
34use risingwave_common::bitmap::Bitmap;
35use risingwave_common::catalog::{
36 ColumnDesc, ColumnId, TableId, TableOption, get_dist_key_in_pk_indices,
37};
38use risingwave_common::config::StreamingConfig;
39use risingwave_common::hash::{VirtualNode, VnodeBitmapExt, VnodeCountCompat};
40use risingwave_common::id::FragmentId;
41use risingwave_common::row::{self, OwnedRow, Row, RowExt};
42use risingwave_common::types::{DataType, ScalarImpl};
43use risingwave_common::util::column_index_mapping::ColIndexMapping;
44use risingwave_common::util::epoch::EpochPair;
45use risingwave_common::util::row_serde::OrderedRowSerde;
46use risingwave_common::util::sort_util::{OrderType, cmp_datum};
47use risingwave_common::util::value_encoding::BasicSerde;
48use risingwave_hummock_sdk::HummockReadEpoch;
49use risingwave_hummock_sdk::key::{
50 CopyFromSlice, TableKey, TableKeyRange, end_bound_of_prefix, is_empty_key_range, next_key,
51 prefix_slice_with_vnode, prefixed_range_with_vnode, start_bound_of_excluded_prefix,
52};
53use risingwave_hummock_sdk::table_watermark::{
54 VnodeWatermark, WatermarkDirection, WatermarkSerdeType, rewrite_range_with_watermark,
55};
56use risingwave_pb::catalog::Table;
57use risingwave_pb::plan_common::StorageTableDesc;
58use risingwave_storage::StateStore;
59use risingwave_storage::error::{ErrorKind, StorageError, StorageResult};
60use risingwave_storage::hummock::CachePolicy;
61use risingwave_storage::mem_table::MemTableError;
62use risingwave_storage::row_serde::find_columns_by_ids;
63use risingwave_storage::row_serde::row_serde_util::{
64 deserialize_pk_with_vnode, serialize_pk, serialize_pk_with_vnode, serialize_row,
65};
66use risingwave_storage::row_serde::value_serde::ValueRowSerde;
67use risingwave_storage::store::*;
68use risingwave_storage::table::{KeyedRow, TableDistribution, should_calculate_prefix_hint};
69use thiserror_ext::AsReport;
70use tracing::{Instrument, trace};
71
72use crate::cache::keyed_cache_may_stale;
73use crate::executor::monitor::streaming_stats::StateTableMetrics;
74use crate::executor::{StreamExecutorError, StreamExecutorResult};
75
76macro_rules! insane_mode_discard_point {
79 () => {{
80 use rand::Rng;
81 if crate::consistency::insane() && rand::rng().random_bool(0.3) {
82 return;
83 }
84 }};
85}
86
87struct VnodeStatistics {
91 min_key: Option<Bytes>,
92 max_key: Option<Bytes>,
93}
94
95impl VnodeStatistics {
96 fn new() -> Self {
97 Self {
98 min_key: None,
99 max_key: None,
100 }
101 }
102
103 fn update_with_key(&mut self, key: &Bytes) {
104 if let Some(min) = &self.min_key {
105 if key < min {
106 self.min_key = Some(key.clone());
107 }
108 } else {
109 self.min_key = Some(key.clone());
110 }
111
112 if let Some(max) = &self.max_key {
113 if key > max {
114 self.max_key = Some(key.clone());
115 }
116 } else {
117 self.max_key = Some(key.clone());
118 }
119 }
120
121 fn can_prune(&self, key: &Bytes) -> bool {
122 if let Some(min) = &self.min_key
123 && key < min
124 {
125 return true;
126 }
127 if let Some(max) = &self.max_key
128 && key > max
129 {
130 return true;
131 }
132 false
133 }
134
135 fn can_prune_range(&self, start: &Bound<Bytes>, end: &Bound<Bytes>) -> bool {
136 if let Some(max) = &self.max_key {
138 match start {
139 Included(s) if s > max => return true,
140 Excluded(s) if s >= max => return true,
141 _ => {}
142 }
143 }
144 if let Some(min) = &self.min_key {
145 match end {
146 Included(e) if e < min => return true,
147 Excluded(e) if e <= min => return true,
148 _ => {}
149 }
150 }
151 false
152 }
153
154 fn pruned_key_range(
155 &self,
156 start: &Bound<Bytes>,
157 end: &Bound<Bytes>,
158 ) -> Option<(Bound<Bytes>, Bound<Bytes>)> {
159 if self.can_prune_range(start, end) {
160 return None;
161 }
162 let new_start = if let Some(min) = &self.min_key {
163 match start {
164 Included(s) if s <= min => Included(min.clone()),
165 Excluded(s) if s < min => Included(min.clone()),
166 _ => start.clone(),
167 }
168 } else {
169 start.clone()
170 };
171
172 let new_end = if let Some(max) = &self.max_key {
173 match end {
174 Included(e) if e >= max => Included(max.clone()),
175 Excluded(e) if e > max => Included(max.clone()),
176 _ => end.clone(),
177 }
178 } else {
179 end.clone()
180 };
181
182 Some((new_start, new_end))
183 }
184}
185
186pub struct StateTableInner<S, SD = BasicSerde, const IS_REPLICATED: bool = false>
189where
190 S: StateStore,
191 SD: ValueRowSerde,
192{
193 table_id: TableId,
195
196 row_store: StateTableRowStore<S::Local, SD>,
198
199 store: S,
201
202 epoch: Option<EpochPair>,
204
205 pk_serde: OrderedRowSerde,
207
208 pk_indices: Vec<usize>,
212
213 distribution: TableDistribution,
219
220 prefix_hint_len: usize,
221
222 value_indices: Option<Vec<usize>>,
223
224 pub clean_watermark_index: Option<usize>,
226 pending_watermark: Option<ScalarImpl>,
228 committed_watermark: Option<ScalarImpl>,
230 watermark_serde: Option<(OrderedRowSerde, WatermarkSerdeType)>,
232
233 data_types: Vec<DataType>,
236
237 i2o_mapping: ColIndexMapping,
243
244 pub output_indices: Vec<usize>,
249
250 op_consistency_level: StateTableOpConsistencyLevel,
251
252 on_post_commit: bool,
255}
256
257pub type StateTable<S> = StateTableInner<S, BasicSerde>;
259pub type ReplicatedStateTable<S, SD> = StateTableInner<S, SD, true>;
262
263pub type FlushedStateTableReader<S, SD = BasicSerde> = StateTableFlushedSnapshotReader<
264 <<S as StateStore>::Local as LocalStateStore>::FlushedSnapshotReader,
265 SD,
266>;
267
268#[derive(Educe)]
269#[educe(Clone)]
270pub struct StateTableFlushedSnapshotReader<R, SD = BasicSerde>
271where
272 R: StateStoreRead,
273 SD: ValueRowSerde,
274{
275 reader: Arc<R>,
276 pk_serde: OrderedRowSerde,
277 vnodes: Arc<Bitmap>,
278 row_serde: Arc<SD>,
279 metrics: Option<StateTableMetrics>,
280}
281
282impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
284where
285 S: StateStore,
286 SD: ValueRowSerde,
287{
288 pub async fn init_epoch(&mut self, epoch: EpochPair) -> StreamExecutorResult<()> {
291 self.row_store
292 .init(epoch, self.distribution.vnodes())
293 .await?;
294 assert_eq!(None, self.epoch.replace(epoch), "should not init for twice");
295 Ok(())
296 }
297
298 pub async fn try_wait_committed_epoch(&self, prev_epoch: u64) -> StorageResult<()> {
299 self.store
300 .try_wait_epoch(
301 HummockReadEpoch::Committed(prev_epoch),
302 TryWaitEpochOptions {
303 table_id: self.table_id,
304 },
305 )
306 .await
307 }
308
309 pub fn state_store(&self) -> &S {
310 &self.store
311 }
312}
313
314fn consistent_old_value_op(
315 row_serde: Arc<impl ValueRowSerde>,
316 is_log_store: bool,
317) -> OpConsistencyLevel {
318 OpConsistencyLevel::ConsistentOldValue {
319 check_old_value: Arc::new(move |first: &Bytes, second: &Bytes| {
320 if first == second {
321 return true;
322 }
323 let first = match row_serde.deserialize(first) {
324 Ok(rows) => rows,
325 Err(e) => {
326 error!(error = %e.as_report(), value = ?first, "failed to deserialize the serialized value");
327 return false;
328 }
329 };
330 let second = match row_serde.deserialize(second) {
331 Ok(rows) => rows,
332 Err(e) => {
333 error!(error = %e.as_report(), value = ?second, "failed to deserialize the serialized value");
334 return false;
335 }
336 };
337 if first != second {
338 error!(first = ?first, second = ?second, "sanity check fail");
339 false
340 } else {
341 true
342 }
343 }),
344 is_log_store,
345 }
346}
347
348macro_rules! dispatch_value_indices {
349 ($value_indices:expr, [$($row_var_name:ident),+], $body:expr) => {
350 if let Some(value_indices) = $value_indices {
351 $(
352 let $row_var_name = $row_var_name.project(value_indices);
353 )+
354 $body
355 } else {
356 $body
357 }
358 };
359}
360
361struct StateTableRowStore<LS: LocalStateStore, SD: ValueRowSerde> {
366 state_store: LS,
367 all_rows: Option<HashMap<VirtualNode, BTreeMap<Bytes, OwnedRow>>>,
368 pending_watermark: Option<(WatermarkDirection, Bytes)>,
372
373 table_id: TableId,
374 row_serde: Arc<SD>,
375 pk_serde: OrderedRowSerde,
377
378 vnode_stats: Option<HashMap<VirtualNode, VnodeStatistics>>,
380 enable_state_table_vnode_stats_pruning: bool,
384 pub metrics: Option<StateTableMetrics>,
386}
387
388impl<LS: LocalStateStore, SD: ValueRowSerde> StateTableRowStore<LS, SD> {
389 async fn may_load_vnode_stats(&mut self, vnode_bitmap: &Bitmap) -> StreamExecutorResult<()> {
390 if self.vnode_stats.is_none() {
391 return Ok(());
392 }
393
394 assert!(self.all_rows.is_none());
396
397 let start_time = Instant::now();
398 let mut stats_map = HashMap::new();
399
400 for vnode in vnode_bitmap.iter_vnodes() {
402 let mut stats = VnodeStatistics::new();
403
404 let memcomparable_range_with_vnode = prefixed_range_with_vnode::<Bytes>(.., vnode);
406 let read_options = ReadOptions {
407 cache_policy: CachePolicy::Fill(Hint::Low),
408 ..Default::default()
409 };
410
411 let mut iter = self
412 .state_store
413 .iter(memcomparable_range_with_vnode.clone(), read_options.clone())
414 .await?;
415 if let Some(item) = iter.try_next().await? {
416 let (key_vnode, key_without_vnode) = item.0.user_key.table_key.split_vnode();
417 assert_eq!(vnode, key_vnode);
418 stats.min_key = Some(Bytes::copy_from_slice(key_without_vnode));
419 }
420
421 let mut rev_iter = self
423 .state_store
424 .rev_iter(memcomparable_range_with_vnode, read_options)
425 .await?;
426 if let Some(item) = rev_iter.try_next().await? {
427 let (key_vnode, key_without_vnode) = item.0.user_key.table_key.split_vnode();
428 assert_eq!(vnode, key_vnode);
429 stats.max_key = Some(Bytes::copy_from_slice(key_without_vnode));
430 }
431
432 stats_map.insert(vnode, stats);
433 }
434
435 self.vnode_stats = Some(stats_map);
436
437 if !cfg!(debug_assertions) {
439 info!(
440 table_id = %self.table_id,
441 vnode_count = vnode_bitmap.count_ones(),
442 duration = ?start_time.elapsed(),
443 "finished initializing vnode statistics"
444 );
445 }
446
447 Ok(())
448 }
449
450 async fn may_reload_all_rows(&mut self, vnode_bitmap: &Bitmap) -> StreamExecutorResult<()> {
451 if let Some(rows) = &mut self.all_rows {
452 rows.clear();
453 let start_time = Instant::now();
454 *rows = try_join_all(vnode_bitmap.iter_vnodes().map(|vnode| {
455 let state_store = &self.state_store;
456 let row_serde = &self.row_serde;
457 async move {
458 let mut rows = BTreeMap::new();
459 let memcomparable_range_with_vnode =
460 prefixed_range_with_vnode::<Bytes>(.., vnode);
461 let stream = deserialize_keyed_row_stream::<Bytes>(
463 state_store
464 .iter(
465 memcomparable_range_with_vnode,
466 ReadOptions {
467 prefix_hint: None,
468 prefetch_options: Default::default(),
469 cache_policy: Default::default(),
470 },
471 )
472 .await?,
473 &**row_serde,
474 );
475 pin_mut!(stream);
476 while let Some((encoded_key, row)) = stream.try_next().await? {
477 let key = TableKey(encoded_key);
478 let (iter_vnode, key) = key.split_vnode_bytes();
479 assert_eq!(vnode, iter_vnode);
480 rows.try_insert(key, row).expect("non-duplicated");
481 }
482 Ok((vnode, rows)) as StreamExecutorResult<_>
483 }
484 }))
485 .await?
486 .into_iter()
487 .collect();
488 if !cfg!(debug_assertions) {
490 info!(table_id = %self.table_id, vnode_count = vnode_bitmap.count_ones(), duration = ?start_time.elapsed(),"finished reloading all rows");
491 }
492 }
493 Ok(())
494 }
495
496 async fn init(&mut self, epoch: EpochPair, vnode_bitmap: &Bitmap) -> StreamExecutorResult<()> {
497 self.state_store.init(InitOptions::new(epoch)).await?;
498 self.may_reload_all_rows(vnode_bitmap).await?;
499 self.may_load_vnode_stats(vnode_bitmap).await
500 }
501
502 async fn update_vnode_bitmap(
503 &mut self,
504 vnodes: Arc<Bitmap>,
505 ) -> StreamExecutorResult<Arc<Bitmap>> {
506 let prev_vnodes = self.state_store.update_vnode_bitmap(vnodes.clone()).await?;
507 self.may_reload_all_rows(&vnodes).await?;
508 self.may_load_vnode_stats(&vnodes).await?;
509
510 Ok(prev_vnodes)
511 }
512
513 async fn try_flush(&mut self) -> StreamExecutorResult<()> {
514 self.state_store.try_flush().await?;
515 Ok(())
516 }
517
518 fn clean_preloaded_rows(
520 &mut self,
521 direction: WatermarkDirection,
522 watermarks: &[VnodeWatermark],
523 serde_type: WatermarkSerdeType,
524 ) {
525 let Some(rows) = &mut self.all_rows else {
526 return;
527 };
528 match serde_type {
529 WatermarkSerdeType::PkPrefix => {
530 for vnode_watermark in watermarks {
531 match direction {
532 WatermarkDirection::Ascending => {
533 for vnode in vnode_watermark.vnode_bitmap().iter_vnodes() {
534 let rows = rows.get_mut(&vnode).expect("covered vnode");
535 *rows = rows.split_off(vnode_watermark.watermark());
537 }
538 }
539 WatermarkDirection::Descending => {
540 let split_off_key = next_key(vnode_watermark.watermark());
542 for vnode in vnode_watermark.vnode_bitmap().iter_vnodes() {
543 let rows = rows.get_mut(&vnode).expect("covered vnode");
544 rows.split_off(split_off_key.as_slice());
547 }
548 }
549 }
550 }
551 }
552 WatermarkSerdeType::NonPkPrefix => {
553 warn!(table_id = %self.table_id, "table enabled preloading rows got disabled by written non pk prefix watermark");
554 self.all_rows = None;
555 }
556 WatermarkSerdeType::Value => {
557 warn!(table_id = %self.table_id, "table enabled preloading rows got disabled by written value watermark");
558 self.all_rows = None;
559 }
560 }
561 }
562
563 fn update_pending_watermark(
566 &mut self,
567 direction: WatermarkDirection,
568 vnode_watermark: VnodeWatermark,
569 ) {
570 self.clean_preloaded_rows(
571 direction,
572 std::slice::from_ref(&vnode_watermark),
573 WatermarkSerdeType::PkPrefix,
574 );
575 self.pending_watermark = Some((direction, vnode_watermark.watermark().clone()));
576 }
577
578 fn narrow_by_pending_watermark(&self, key_range: &mut TableKeyRange) {
579 if let Some((direction, watermark)) = &self.pending_watermark {
580 rewrite_range_with_watermark(*direction, watermark, key_range);
581 }
582 }
583
584 fn below_pending_watermark(&self, key: &TableKey<Bytes>) -> bool {
585 let mut key_range = (Bound::Included(key.clone()), Bound::Included(key.clone()));
586 self.narrow_by_pending_watermark(&mut key_range);
587 is_empty_key_range(&key_range)
588 }
589
590 async fn seal_current_epoch(
591 &mut self,
592 next_epoch: u64,
593 table_watermarks: Option<(WatermarkDirection, Vec<VnodeWatermark>, WatermarkSerdeType)>,
594 switch_consistent_op: Option<StateTableOpConsistencyLevel>,
595 ) -> StreamExecutorResult<()> {
596 if let Some((direction, watermarks, serde_type)) = &table_watermarks {
597 self.clean_preloaded_rows(*direction, watermarks, *serde_type);
598 }
599 self.state_store
600 .flush()
601 .instrument(tracing::info_span!("state_table_flush"))
602 .await?;
603 let switch_op_consistency_level =
604 switch_consistent_op.map(|new_consistency_level| match new_consistency_level {
605 StateTableOpConsistencyLevel::Inconsistent => OpConsistencyLevel::Inconsistent,
606 StateTableOpConsistencyLevel::ConsistentOldValue => {
607 consistent_old_value_op(self.row_serde.clone(), false)
608 }
609 StateTableOpConsistencyLevel::LogStoreEnabled => {
610 consistent_old_value_op(self.row_serde.clone(), true)
611 }
612 });
613 self.state_store.seal_current_epoch(
614 next_epoch,
615 SealCurrentEpochOptions {
616 table_watermarks,
617 switch_op_consistency_level,
618 },
619 );
620 Ok(())
621 }
622}
623
624#[derive(Eq, PartialEq, Copy, Clone, Debug)]
625pub enum StateTableOpConsistencyLevel {
626 Inconsistent,
628 ConsistentOldValue,
632 LogStoreEnabled,
635}
636
637pub struct StateTableBuilder<S, SD, const IS_REPLICATED: bool, PreloadAllRow> {
638 table_id: TableId,
640 table_name_for_debug: String,
641 table_columns: Vec<ColumnDesc>,
642 order_types: Vec<OrderType>,
643 pk_indices: Vec<usize>,
644 dist_key_in_pk_indices: Vec<usize>,
645 vnode_col_idx_in_pk: Option<usize>,
646 expected_vnode_count: usize,
647 value_indices: Vec<usize>,
648 prefix_hint_len: usize,
649 retention_seconds: Option<u32>,
650 versioned: bool,
651 fragment_id: FragmentId,
652 clean_watermark_index: Option<usize>,
653
654 store: S,
656 vnodes: Option<Arc<Bitmap>>,
657 op_consistency_level: Option<StateTableOpConsistencyLevel>,
658 output_column_ids: Option<Vec<ColumnId>>,
659 preload_all_rows: PreloadAllRow,
660 enable_vnode_key_stats: Option<bool>,
661 enable_state_table_vnode_stats_pruning: bool,
664 metrics: Option<StateTableMetrics>,
665
666 _serde: PhantomData<SD>,
667}
668
669impl<S: StateStore, SD: ValueRowSerde, const IS_REPLICATED: bool>
670 StateTableBuilder<S, SD, IS_REPLICATED, ()>
671{
672 fn with_preload_all_rows(
673 self,
674 preload_all_rows: bool,
675 ) -> StateTableBuilder<S, SD, IS_REPLICATED, bool> {
676 StateTableBuilder {
677 table_id: self.table_id,
678 table_name_for_debug: self.table_name_for_debug,
679 table_columns: self.table_columns,
680 order_types: self.order_types,
681 pk_indices: self.pk_indices,
682 dist_key_in_pk_indices: self.dist_key_in_pk_indices,
683 vnode_col_idx_in_pk: self.vnode_col_idx_in_pk,
684 expected_vnode_count: self.expected_vnode_count,
685 value_indices: self.value_indices,
686 prefix_hint_len: self.prefix_hint_len,
687 retention_seconds: self.retention_seconds,
688 versioned: self.versioned,
689 fragment_id: self.fragment_id,
690 clean_watermark_index: self.clean_watermark_index,
691 store: self.store,
692 vnodes: self.vnodes,
693 op_consistency_level: self.op_consistency_level,
694 output_column_ids: self.output_column_ids,
695 preload_all_rows,
696 enable_vnode_key_stats: self.enable_vnode_key_stats,
697 enable_state_table_vnode_stats_pruning: self.enable_state_table_vnode_stats_pruning,
698 metrics: self.metrics,
699 _serde: Default::default(),
700 }
701 }
702
703 pub fn enable_preload_all_rows_by_config(
704 self,
705 config: &StreamingConfig,
706 ) -> StateTableBuilder<S, SD, IS_REPLICATED, bool> {
707 let developer = &config.developer;
708 let preload_all_rows = if developer.default_enable_mem_preload_state_table {
709 !developer
710 .mem_preload_state_table_ids_blacklist
711 .contains(&self.table_id.as_raw_id())
712 } else {
713 developer
714 .mem_preload_state_table_ids_whitelist
715 .contains(&self.table_id.as_raw_id())
716 };
717 self.with_preload_all_rows(preload_all_rows)
718 }
719
720 pub fn forbid_preload_all_rows(self) -> StateTableBuilder<S, SD, IS_REPLICATED, bool> {
721 self.with_preload_all_rows(false)
722 }
723}
724
725impl<S: StateStore, SD: ValueRowSerde, const IS_REPLICATED: bool, PreloadAllRow>
726 StateTableBuilder<S, SD, IS_REPLICATED, PreloadAllRow>
727{
728 pub fn with_op_consistency_level(
729 mut self,
730 op_consistency_level: StateTableOpConsistencyLevel,
731 ) -> Self {
732 self.op_consistency_level = Some(op_consistency_level);
733 self
734 }
735
736 pub fn enable_vnode_key_stats(mut self, enable: bool, config: &StreamingConfig) -> Self {
737 self.enable_vnode_key_stats = Some(enable);
738 self.enable_state_table_vnode_stats_pruning =
739 enable && config.developer.enable_state_table_vnode_stats_pruning;
740 self
741 }
742
743 pub fn with_metrics(mut self, metrics: StateTableMetrics) -> Self {
744 self.metrics = Some(metrics);
745 self
746 }
747}
748
749impl<S: StateStore, SD: ValueRowSerde, PreloadAllRow>
750 StateTableBuilder<S, SD, true, PreloadAllRow>
751{
752 pub fn with_output_column_ids(mut self, output_column_ids: Vec<ColumnId>) -> Self {
753 self.output_column_ids = Some(output_column_ids);
754 self
755 }
756}
757
758impl<S: StateStore, SD: ValueRowSerde, const IS_REPLICATED: bool>
759 StateTableBuilder<S, SD, IS_REPLICATED, bool>
760{
761 pub async fn build(self) -> StateTableInner<S, SD, IS_REPLICATED> {
762 let mut preload_all_rows = self.preload_all_rows;
763 if preload_all_rows
764 && let Err(e) =
765 risingwave_common::license::Feature::StateTableMemoryPreload.check_available()
766 {
767 warn!(table_id=%self.table_id, e=%e.as_report(), "table configured to preload rows to memory but disabled by license");
768 preload_all_rows = false;
769 }
770
771 let should_enable_vnode_key_stats = if preload_all_rows
772 && let Some(enable_vnode_key_stats) = self.enable_vnode_key_stats
773 && enable_vnode_key_stats
774 {
775 false
776 } else {
777 self.enable_vnode_key_stats.unwrap_or(false)
778 };
779 self.build_inner(preload_all_rows, should_enable_vnode_key_stats)
780 .await
781 }
782}
783
784impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
789where
790 S: StateStore,
791 SD: ValueRowSerde,
792{
793 #[cfg(any(test, feature = "test"))]
797 pub async fn from_table_catalog(
798 table_catalog: &Table,
799 store: S,
800 vnodes: Option<Arc<Bitmap>>,
801 ) -> Self {
802 StateTableBuilder::new(table_catalog, store, vnodes)
803 .forbid_preload_all_rows()
804 .build()
805 .await
806 }
807
808 pub async fn from_table_catalog_inconsistent_op(
810 table_catalog: &Table,
811 store: S,
812 vnodes: Option<Arc<Bitmap>>,
813 ) -> Self {
814 StateTableBuilder::new(table_catalog, store, vnodes)
815 .with_op_consistency_level(StateTableOpConsistencyLevel::Inconsistent)
816 .forbid_preload_all_rows()
817 .build()
818 .await
819 }
820}
821
822impl<S: StateStore, SD: ValueRowSerde, const IS_REPLICATED: bool>
823 StateTableBuilder<S, SD, IS_REPLICATED, ()>
824{
825 pub fn new(table_catalog: &Table, store: S, vnodes: Option<Arc<Bitmap>>) -> Self {
826 let table_id = table_catalog.id;
827 let table_columns: Vec<ColumnDesc> = table_catalog
828 .columns
829 .iter()
830 .map(|col| col.column_desc.as_ref().unwrap().into())
831 .collect();
832 let order_types: Vec<OrderType> = table_catalog
833 .pk
834 .iter()
835 .map(|col_order| OrderType::from_protobuf(col_order.get_order_type().unwrap()))
836 .collect();
837 let dist_key_indices: Vec<usize> = table_catalog
838 .distribution_key
839 .iter()
840 .map(|dist_index| *dist_index as usize)
841 .collect();
842
843 let pk_indices = table_catalog
844 .pk
845 .iter()
846 .map(|col_order| col_order.column_index as usize)
847 .collect_vec();
848
849 let dist_key_in_pk_indices = if table_catalog.get_dist_key_in_pk().is_empty() {
851 get_dist_key_in_pk_indices(&dist_key_indices, &pk_indices).unwrap()
852 } else {
853 table_catalog
854 .get_dist_key_in_pk()
855 .iter()
856 .map(|idx| *idx as usize)
857 .collect()
858 };
859
860 let vnode_col_idx_in_pk = table_catalog.vnode_col_index.as_ref().and_then(|idx| {
861 let vnode_col_idx = *idx as usize;
862 pk_indices.iter().position(|&i| vnode_col_idx == i)
863 });
864 let value_indices = table_catalog
865 .value_indices
866 .iter()
867 .map(|val| *val as usize)
868 .collect_vec();
869 let clean_watermark_indices = table_catalog.get_clean_watermark_column_indices();
870 if clean_watermark_indices.len() > 1 {
871 unimplemented!("multiple clean watermark columns are not supported yet")
872 }
873 let clean_watermark_index = clean_watermark_indices.first().map(|&i| i as usize);
874
875 Self {
876 table_id,
877 table_name_for_debug: table_catalog.name.clone(),
878 table_columns,
879 order_types,
880 pk_indices,
881 dist_key_in_pk_indices,
882 vnode_col_idx_in_pk,
883 expected_vnode_count: table_catalog.vnode_count(),
884 value_indices,
885 prefix_hint_len: table_catalog.read_prefix_len_hint as usize,
886 retention_seconds: table_catalog.retention_seconds,
887 versioned: table_catalog.version.is_some(),
888 fragment_id: table_catalog.fragment_id,
889 clean_watermark_index,
890 store,
891 vnodes,
892 op_consistency_level: None,
893 output_column_ids: None,
894 preload_all_rows: (),
895 enable_vnode_key_stats: None,
896 enable_state_table_vnode_stats_pruning: false,
897 metrics: None,
898 _serde: Default::default(),
899 }
900 }
901}
902
903impl<S: StateStore, SD: ValueRowSerde, const IS_REPLICATED: bool>
904 StateTableBuilder<S, SD, IS_REPLICATED, bool>
905{
906 async fn build_inner(
907 self,
908 preload_all_rows: bool,
909 should_enable_vnode_key_stats: bool,
910 ) -> StateTableInner<S, SD, IS_REPLICATED> {
911 let table_id = self.table_id;
912 let table_columns = self.table_columns;
913 let order_types = self.order_types;
914 let pk_indices = self.pk_indices;
915 let dist_key_in_pk_indices = self.dist_key_in_pk_indices;
916 let vnode_col_idx_in_pk = self.vnode_col_idx_in_pk;
917 let prefix_hint_len = self.prefix_hint_len;
918 let metrics = self.metrics;
919
920 let op_consistency_level = self
921 .op_consistency_level
922 .unwrap_or(StateTableOpConsistencyLevel::ConsistentOldValue);
923
924 let output_column_ids = self.output_column_ids.unwrap_or_default();
925
926 let data_types: Vec<DataType> = table_columns
927 .iter()
928 .map(|col| col.data_type.clone())
929 .collect();
930
931 if IS_REPLICATED && prefix_hint_len > 0 {
935 assert!(
936 dist_key_in_pk_indices.iter().all(|&d| d < prefix_hint_len),
937 "replicated state table: distribution key indices {:?} must all be covered by \
938 prefix_hint_len {}",
939 dist_key_in_pk_indices,
940 prefix_hint_len,
941 );
942 }
943
944 let distribution =
945 TableDistribution::new(self.vnodes, dist_key_in_pk_indices, vnode_col_idx_in_pk);
946 assert_eq!(
947 distribution.vnode_count(),
948 self.expected_vnode_count,
949 "vnode count mismatch, scanning table {} under wrong distribution?",
950 self.table_name_for_debug,
951 );
952
953 let pk_data_types = pk_indices
954 .iter()
955 .map(|i| table_columns[*i].data_type.clone())
956 .collect();
957 let pk_serde = OrderedRowSerde::new(pk_data_types, order_types);
958
959 let input_value_indices = self.value_indices;
960
961 let no_shuffle_value_indices = (0..table_columns.len()).collect_vec();
962
963 let value_indices = match input_value_indices.len() == table_columns.len()
965 && input_value_indices == no_shuffle_value_indices
966 {
967 true => None,
968 false => Some(input_value_indices.clone()),
969 };
970
971 let row_serde = Arc::new(SD::new(
972 Arc::from_iter(input_value_indices.iter().copied()),
973 Arc::from(table_columns.clone().into_boxed_slice()),
974 ));
975
976 let state_table_op_consistency_level = op_consistency_level;
977 let op_consistency_level = match state_table_op_consistency_level {
978 StateTableOpConsistencyLevel::Inconsistent => OpConsistencyLevel::Inconsistent,
979 StateTableOpConsistencyLevel::ConsistentOldValue => {
980 consistent_old_value_op(row_serde.clone(), false)
981 }
982 StateTableOpConsistencyLevel::LogStoreEnabled => {
983 consistent_old_value_op(row_serde.clone(), true)
984 }
985 };
986
987 let table_option = TableOption::new(self.retention_seconds);
988 let new_local_options = if IS_REPLICATED {
989 NewLocalOptions::new_replicated(
990 table_id,
991 self.fragment_id,
992 op_consistency_level,
993 table_option,
994 distribution.vnodes().clone(),
995 )
996 } else {
997 NewLocalOptions::new(
998 table_id,
999 self.fragment_id,
1000 op_consistency_level,
1001 table_option,
1002 distribution.vnodes().clone(),
1003 true,
1004 )
1005 };
1006 let local_state_store = self.store.new_local(new_local_options).await;
1007
1008 assert_eq!(self.versioned, row_serde.kind().is_column_aware());
1014
1015 let output_column_ids_to_input_idx = output_column_ids
1017 .iter()
1018 .enumerate()
1019 .map(|(pos, id)| (*id, pos))
1020 .collect::<HashMap<_, _>>();
1021
1022 let columns = table_columns;
1023
1024 let mut i2o_mapping = vec![None; columns.len()];
1028 for (i, column) in columns.iter().enumerate() {
1029 if let Some(pos) = output_column_ids_to_input_idx.get(&column.column_id) {
1030 i2o_mapping[i] = Some(*pos);
1031 }
1032 }
1033 let i2o_mapping = ColIndexMapping::new(i2o_mapping, output_column_ids.len());
1035
1036 let (_, output_indices) = find_columns_by_ids(&columns[..], &output_column_ids);
1038
1039 if IS_REPLICATED {
1042 assert!(
1043 pk_indices
1044 .iter()
1045 .all(|&pk_idx| output_indices.contains(&pk_idx)),
1046 "all pk columns must be included in output_column_ids for replicated state table"
1047 );
1048 }
1049
1050 let clean_watermark_index = self.clean_watermark_index;
1051 let watermark_serde = clean_watermark_index.map(|idx| {
1052 let pk_idx = pk_indices.iter().position(|&i| i == idx);
1053 let (watermark_serde, watermark_serde_type) = match pk_idx {
1054 Some(0) => (pk_serde.index(0).into_owned(), WatermarkSerdeType::PkPrefix),
1055 Some(pk_idx) => (
1056 pk_serde.index(pk_idx).into_owned(),
1057 WatermarkSerdeType::NonPkPrefix,
1058 ),
1059 None => (
1060 OrderedRowSerde::new(
1061 vec![data_types[idx].clone()],
1062 vec![OrderType::ascending()],
1063 ),
1064 WatermarkSerdeType::Value,
1065 ),
1066 };
1067 (watermark_serde, watermark_serde_type)
1068 });
1069
1070 let committed_watermark = if let Some((deser, _)) = watermark_serde.as_ref() {
1072 distribution
1073 .vnodes()
1074 .iter_vnodes()
1075 .filter_map(|vnode| {
1076 let bytes = local_state_store.get_table_watermark(vnode)?;
1077 let datum = deser.deserialize(&bytes).ok().and_then(|row| {
1078 assert!(row.len() == 1);
1079 row[0].clone()
1080 });
1081 if datum.is_none() {
1082 tracing::error!(
1083 ?vnode,
1084 watermark = ?bytes,
1085 "Failed to deserialize persisted watermark from state store.",
1086 );
1087 }
1088 datum
1089 })
1090 .max_by(|a, b| cmp_datum(Some(a), Some(b), OrderType::ascending()))
1091 } else {
1092 None
1093 };
1094
1095 StateTableInner {
1096 table_id,
1097 row_store: StateTableRowStore {
1098 all_rows: preload_all_rows.then(HashMap::new),
1099 pending_watermark: None,
1100 state_store: local_state_store,
1101 row_serde,
1102 pk_serde: pk_serde.clone(),
1103 table_id,
1104 vnode_stats: should_enable_vnode_key_stats.then(HashMap::new),
1106 enable_state_table_vnode_stats_pruning: self.enable_state_table_vnode_stats_pruning,
1107 metrics,
1108 },
1109 store: self.store,
1110 epoch: None,
1111 pk_serde,
1112 pk_indices,
1113 distribution,
1114 prefix_hint_len,
1115 value_indices,
1116 pending_watermark: None,
1117 committed_watermark,
1118 watermark_serde,
1119 data_types,
1120 output_indices,
1121 i2o_mapping,
1122 op_consistency_level: state_table_op_consistency_level,
1123 clean_watermark_index,
1124 on_post_commit: false,
1125 }
1126 }
1127}
1128
1129impl<S: StateStore, SD: ValueRowSerde, const IS_REPLICATED: bool>
1130 StateTableBuilder<S, SD, IS_REPLICATED, ()>
1131{
1132 pub fn new_from_storage_table_desc(
1133 table_desc: &StorageTableDesc,
1134 store: S,
1135 vnodes: Option<Arc<Bitmap>>,
1136 fragment_id: FragmentId,
1137 ) -> Self {
1138 let table_id = table_desc.table_id;
1139 let table_columns: Vec<ColumnDesc> =
1140 table_desc.columns.iter().map(ColumnDesc::from).collect();
1141 let order_types: Vec<OrderType> = table_desc
1142 .pk
1143 .iter()
1144 .map(|col_order| OrderType::from_protobuf(col_order.get_order_type().unwrap()))
1145 .collect();
1146 let pk_indices = table_desc
1147 .pk
1148 .iter()
1149 .map(|col_order| col_order.column_index as usize)
1150 .collect_vec();
1151 let dist_key_in_pk_indices = table_desc
1152 .dist_key_in_pk_indices
1153 .iter()
1154 .map(|&idx| idx as usize)
1155 .collect();
1156 let vnode_col_idx_in_pk = table_desc.vnode_col_idx_in_pk.map(|k| k as usize);
1159 let raw_value_indices = table_desc
1160 .value_indices
1161 .iter()
1162 .map(|val| *val as usize)
1163 .collect_vec();
1164
1165 Self {
1166 table_id,
1167 table_name_for_debug: table_id.to_string(),
1168 table_columns,
1169 order_types,
1170 pk_indices,
1171 dist_key_in_pk_indices,
1172 vnode_col_idx_in_pk,
1173 expected_vnode_count: table_desc.vnode_count(),
1174 value_indices: raw_value_indices,
1175 prefix_hint_len: table_desc.read_prefix_len_hint as usize,
1176 retention_seconds: table_desc.retention_seconds,
1177 versioned: table_desc.versioned,
1178 fragment_id,
1179 clean_watermark_index: None,
1180 store,
1181 vnodes,
1182 op_consistency_level: None,
1183 output_column_ids: None,
1184 preload_all_rows: (),
1185 enable_vnode_key_stats: None,
1186 enable_state_table_vnode_stats_pruning: false,
1187 metrics: None,
1188 _serde: Default::default(),
1189 }
1190 }
1191}
1192
1193impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
1194where
1195 S: StateStore,
1196 SD: ValueRowSerde,
1197{
1198 pub fn get_data_types(&self) -> &[DataType] {
1199 &self.data_types
1200 }
1201
1202 pub fn table_id(&self) -> TableId {
1203 self.table_id
1204 }
1205
1206 fn compute_prefix_vnode(&self, pk_prefix: &impl Row) -> VirtualNode {
1208 self.distribution
1209 .try_compute_vnode_by_pk_prefix(pk_prefix)
1210 .expect("For streaming, the given prefix must be enough to calculate the vnode")
1211 }
1212
1213 pub fn compute_vnode_by_pk(&self, pk: impl Row) -> VirtualNode {
1215 self.distribution.compute_vnode_by_pk(pk)
1216 }
1217
1218 pub fn pk_indices(&self) -> &[usize] {
1221 &self.pk_indices
1222 }
1223
1224 pub fn pk_in_output_indices(&self) -> Option<Vec<usize>> {
1228 assert!(IS_REPLICATED);
1229 self.pk_indices
1230 .iter()
1231 .map(|&i| self.output_indices.iter().position(|&j| i == j))
1232 .collect()
1233 }
1234
1235 pub fn pk_serde(&self) -> &OrderedRowSerde {
1236 &self.pk_serde
1237 }
1238
1239 pub fn vnodes(&self) -> &Arc<Bitmap> {
1240 self.distribution.vnodes()
1241 }
1242
1243 pub fn flushed_snapshot_reader(&self) -> FlushedStateTableReader<S, SD> {
1244 StateTableFlushedSnapshotReader {
1245 reader: Arc::new(self.row_store.state_store.new_flushed_snapshot_reader()),
1246 pk_serde: self.pk_serde.clone(),
1247 vnodes: self.distribution.vnodes().clone(),
1248 row_serde: self.row_store.row_serde.clone(),
1249 metrics: self.row_store.metrics.clone(),
1250 }
1251 }
1252
1253 pub fn value_indices(&self) -> &Option<Vec<usize>> {
1254 &self.value_indices
1255 }
1256
1257 pub fn is_consistent_op(&self) -> bool {
1258 matches!(
1259 self.op_consistency_level,
1260 StateTableOpConsistencyLevel::ConsistentOldValue
1261 | StateTableOpConsistencyLevel::LogStoreEnabled
1262 )
1263 }
1264
1265 pub fn metrics(&self) -> Option<&StateTableMetrics> {
1266 self.row_store.metrics.as_ref()
1267 }
1268}
1269
1270impl<S, SD> StateTableInner<S, SD, true>
1271where
1272 S: StateStore,
1273 SD: ValueRowSerde,
1274{
1275 pub async fn new_replicated(
1277 table_catalog: &Table,
1278 store: S,
1279 vnodes: Option<Arc<Bitmap>>,
1280 output_column_ids: Vec<ColumnId>,
1281 ) -> Self {
1282 StateTableBuilder::new(table_catalog, store, vnodes)
1285 .with_op_consistency_level(StateTableOpConsistencyLevel::Inconsistent)
1286 .with_output_column_ids(output_column_ids)
1287 .forbid_preload_all_rows()
1288 .build()
1289 .await
1290 }
1291}
1292
1293impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
1295where
1296 S: StateStore,
1297 SD: ValueRowSerde,
1298{
1299 pub async fn get_row(&self, pk: impl Row) -> StreamExecutorResult<Option<OwnedRow>> {
1301 let (serialized_pk, prefix_hint) = self.serialize_pk_and_get_prefix_hint(&pk);
1302 let row = self.row_store.get(serialized_pk, prefix_hint).await?;
1303 match row {
1304 Some(row) => {
1305 if IS_REPLICATED {
1306 let row = row.project(&self.output_indices);
1309 Ok(Some(row.into_owned_row()))
1310 } else {
1311 Ok(Some(row))
1312 }
1313 }
1314 None => Ok(None),
1315 }
1316 }
1317
1318 pub async fn exists(&self, pk: impl Row) -> StreamExecutorResult<bool> {
1320 let (serialized_pk, prefix_hint) = self.serialize_pk_and_get_prefix_hint(&pk);
1321 self.row_store.exists(serialized_pk, prefix_hint).await
1322 }
1323
1324 fn serialize_pk(&self, pk: &impl Row) -> TableKey<Bytes> {
1325 assert!(pk.len() <= self.pk_indices.len());
1326 serialize_pk_with_vnode(pk, &self.pk_serde, self.compute_vnode_by_pk(pk))
1327 }
1328
1329 fn serialize_pk_and_get_prefix_hint(&self, pk: &impl Row) -> (TableKey<Bytes>, Option<Bytes>) {
1330 let serialized_pk = self.serialize_pk(&pk);
1331 let prefix_hint = if should_calculate_prefix_hint(self.prefix_hint_len, pk.len(), false) {
1332 Some(serialized_pk.slice(VirtualNode::SIZE..))
1333 } else {
1334 #[cfg(debug_assertions)]
1335 if self.prefix_hint_len != 0 {
1336 warn!(
1337 "prefix_hint_len is not equal to pk.len(), may not be able to utilize bloom filter"
1338 );
1339 }
1340 None
1341 };
1342 (serialized_pk, prefix_hint)
1343 }
1344}
1345
1346impl<LS: LocalStateStore, SD: ValueRowSerde> StateTableRowStore<LS, SD> {
1347 async fn get(
1348 &self,
1349 key_bytes: TableKey<Bytes>,
1350 prefix_hint: Option<Bytes>,
1351 ) -> StreamExecutorResult<Option<OwnedRow>> {
1352 if let Some(m) = &self.metrics {
1353 m.get_count.inc();
1354 }
1355 if let Some(rows) = &self.all_rows {
1356 let (vnode, key) = key_bytes.split_vnode_bytes();
1357 return Ok(rows.get(&vnode).expect("covered vnode").get(&key).cloned());
1358 }
1359 if self.below_pending_watermark(&key_bytes) {
1360 return Ok(None);
1361 }
1362
1363 let should_prune = if let Some(stats) = &self.vnode_stats
1365 && let (vnode, key) = key_bytes.split_vnode_bytes()
1366 && let Some(vnode_stat) = stats.get(&vnode)
1367 && vnode_stat.can_prune(&key)
1368 {
1369 if let Some(m) = &self.metrics {
1370 m.get_vnode_pruned_count.inc();
1371 }
1372 true
1373 } else {
1374 false
1375 };
1376
1377 if should_prune && self.enable_state_table_vnode_stats_pruning {
1378 return Ok(None);
1379 }
1380
1381 let read_options = ReadOptions {
1382 prefix_hint,
1383 cache_policy: CachePolicy::Fill(Hint::Normal),
1384 ..Default::default()
1385 };
1386
1387 let result = self
1388 .state_store
1389 .on_key_value(key_bytes, read_options, move |_, value| {
1390 let row = self.row_serde.deserialize(value)?;
1391 Ok(OwnedRow::new(row))
1392 })
1393 .await
1394 .map_err(Into::<StreamExecutorError>::into)?;
1395
1396 if should_prune && result.is_some() {
1398 tracing::warn!(
1399 table_id = %self.table_id,
1400 "vnode stats pruning dry run fails for get. This will not affect correctness."
1401 );
1402 }
1403
1404 Ok(result)
1405 }
1406
1407 async fn exists(
1408 &self,
1409 key_bytes: TableKey<Bytes>,
1410 prefix_hint: Option<Bytes>,
1411 ) -> StreamExecutorResult<bool> {
1412 if let Some(m) = &self.metrics {
1413 m.get_count.inc();
1414 }
1415 if let Some(rows) = &self.all_rows {
1416 let (vnode, key) = key_bytes.split_vnode_bytes();
1417 return Ok(rows.get(&vnode).expect("covered vnode").contains_key(&key));
1418 }
1419 if self.below_pending_watermark(&key_bytes) {
1420 return Ok(false);
1421 }
1422
1423 let should_prune = if let Some(stats) = &self.vnode_stats
1425 && let (vnode, key) = key_bytes.split_vnode_bytes()
1426 && let Some(vnode_stat) = stats.get(&vnode)
1427 && vnode_stat.can_prune(&key)
1428 {
1429 if let Some(m) = &self.metrics {
1430 m.get_vnode_pruned_count.inc();
1431 }
1432 true
1433 } else {
1434 false
1435 };
1436
1437 if should_prune && self.enable_state_table_vnode_stats_pruning {
1438 return Ok(false);
1439 }
1440
1441 let read_options = ReadOptions {
1442 prefix_hint,
1443 cache_policy: CachePolicy::Fill(Hint::Normal),
1444 ..Default::default()
1445 };
1446 let result = self
1447 .state_store
1448 .on_key_value(key_bytes, read_options, move |_, _| Ok(()))
1449 .await?;
1450 let exists = result.is_some();
1451
1452 if should_prune && exists {
1454 tracing::warn!(
1455 table_id = %self.table_id,
1456 "vnode stats pruning dry run fails for exists. This will not affect correctness."
1457 );
1458 }
1459
1460 Ok(exists)
1461 }
1462}
1463
1464#[must_use]
1479pub struct StateTablePostCommit<'a, S, SD = BasicSerde, const IS_REPLICATED: bool = false>
1480where
1481 S: StateStore,
1482 SD: ValueRowSerde,
1483{
1484 inner: &'a mut StateTableInner<S, SD, IS_REPLICATED>,
1485}
1486
1487impl<'a, S, SD, const IS_REPLICATED: bool> StateTablePostCommit<'a, S, SD, IS_REPLICATED>
1488where
1489 S: StateStore,
1490 SD: ValueRowSerde,
1491{
1492 pub async fn post_yield_barrier(
1497 mut self,
1498 new_vnodes: Option<Arc<Bitmap>>,
1499 ) -> StreamExecutorResult<
1500 Option<(
1501 (
1502 Arc<Bitmap>,
1503 Arc<Bitmap>,
1504 &'a mut StateTableInner<S, SD, IS_REPLICATED>,
1505 ),
1506 bool,
1507 )>,
1508 > {
1509 self.inner.on_post_commit = false;
1510 Ok(if let Some(new_vnodes) = new_vnodes {
1511 let (old_vnodes, keyed_cache_may_stale) =
1512 self.update_vnode_bitmap(new_vnodes.clone()).await?;
1513 Some(((new_vnodes, old_vnodes, self.inner), keyed_cache_may_stale))
1514 } else {
1515 None
1516 })
1517 }
1518
1519 pub fn inner(&self) -> &StateTableInner<S, SD, IS_REPLICATED> {
1520 &*self.inner
1521 }
1522
1523 async fn update_vnode_bitmap(
1525 &mut self,
1526 new_vnodes: Arc<Bitmap>,
1527 ) -> StreamExecutorResult<(Arc<Bitmap>, bool)> {
1528 let prev_vnodes = self
1529 .inner
1530 .row_store
1531 .update_vnode_bitmap(new_vnodes.clone())
1532 .await?;
1533 assert_eq!(
1534 &prev_vnodes,
1535 self.inner.vnodes(),
1536 "state table and state store vnode bitmap mismatches"
1537 );
1538
1539 if self.inner.distribution.is_singleton() {
1540 assert_eq!(
1541 &new_vnodes,
1542 self.inner.vnodes(),
1543 "should not update vnode bitmap for singleton table"
1544 );
1545 }
1546 assert_eq!(self.inner.vnodes().len(), new_vnodes.len());
1547
1548 let keyed_cache_may_stale = keyed_cache_may_stale(self.inner.vnodes(), &new_vnodes);
1549
1550 if keyed_cache_may_stale {
1551 self.inner.pending_watermark = None;
1552 self.inner.row_store.pending_watermark = None;
1553 }
1554
1555 Ok((
1556 self.inner.distribution.update_vnode_bitmap(new_vnodes),
1557 keyed_cache_may_stale,
1558 ))
1559 }
1560}
1561
1562impl<LS: LocalStateStore, SD: ValueRowSerde> StateTableRowStore<LS, SD> {
1564 fn handle_mem_table_error(&self, e: StorageError) {
1565 let e = match e.into_inner() {
1566 ErrorKind::MemTable(e) => e,
1567 _ => unreachable!("should only get memtable error"),
1568 };
1569 match *e {
1570 MemTableError::InconsistentOperation { key, prev, new, .. } => {
1571 let (vnode, key) = deserialize_pk_with_vnode(&key, &self.pk_serde).unwrap();
1572 panic!(
1573 "mem-table operation inconsistent! table_id: {}, vnode: {}, key: {:?}, prev: {}, new: {}",
1574 self.table_id,
1575 vnode,
1576 key,
1577 prev.debug_fmt(&*self.row_serde),
1578 new.debug_fmt(&*self.row_serde),
1579 )
1580 }
1581 }
1582 }
1583
1584 fn insert(&mut self, key: TableKey<Bytes>, value: impl Row) {
1585 insane_mode_discard_point!();
1586 let value_bytes = self.row_serde.serialize(&value).into();
1587
1588 let (vnode, key_without_vnode) = key.split_vnode_bytes();
1589
1590 if self.all_rows.is_none()
1592 && let Some(stats) = &mut self.vnode_stats
1593 && let Some(vnode_stat) = stats.get_mut(&vnode)
1594 {
1595 vnode_stat.update_with_key(&key_without_vnode);
1596 }
1597
1598 if let Some(rows) = &mut self.all_rows {
1599 rows.get_mut(&vnode)
1600 .expect("covered vnode")
1601 .insert(key_without_vnode, value.into_owned_row());
1602 }
1603 self.state_store
1604 .insert(key, value_bytes, None)
1605 .unwrap_or_else(|e| self.handle_mem_table_error(e));
1606 }
1607
1608 fn delete(&mut self, key: TableKey<Bytes>, value: impl Row) {
1609 insane_mode_discard_point!();
1610 let value_bytes = self.row_serde.serialize(value).into();
1611
1612 let (vnode, key_without_vnode) = key.split_vnode_bytes();
1613
1614 if self.all_rows.is_none()
1615 && let Some(stats) = &mut self.vnode_stats
1616 && let Some(vnode_stat) = stats.get_mut(&vnode)
1617 {
1618 vnode_stat.update_with_key(&key_without_vnode);
1619 }
1620
1621 if let Some(rows) = &mut self.all_rows {
1622 rows.get_mut(&vnode)
1623 .expect("covered vnode")
1624 .remove(&key_without_vnode);
1625 }
1626 self.state_store
1627 .delete(key, value_bytes)
1628 .unwrap_or_else(|e| self.handle_mem_table_error(e));
1629 }
1630
1631 fn update(&mut self, key_bytes: TableKey<Bytes>, old_value: impl Row, new_value: impl Row) {
1632 insane_mode_discard_point!();
1633 let new_value_bytes = self.row_serde.serialize(&new_value).into();
1634 let old_value_bytes = self.row_serde.serialize(old_value).into();
1635
1636 let (vnode, key_without_vnode) = key_bytes.split_vnode_bytes();
1637
1638 if self.all_rows.is_none()
1641 && let Some(stats) = &mut self.vnode_stats
1642 && let Some(vnode_stat) = stats.get_mut(&vnode)
1643 {
1644 vnode_stat.update_with_key(&key_without_vnode);
1645 }
1646
1647 if let Some(rows) = &mut self.all_rows {
1648 rows.get_mut(&vnode)
1649 .expect("covered vnode")
1650 .insert(key_without_vnode, new_value.into_owned_row());
1651 }
1652 self.state_store
1653 .insert(key_bytes, new_value_bytes, Some(old_value_bytes))
1654 .unwrap_or_else(|e| self.handle_mem_table_error(e));
1655 }
1656}
1657
1658impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
1659where
1660 S: StateStore,
1661 SD: ValueRowSerde,
1662{
1663 pub fn insert(&mut self, value: impl Row) {
1666 let pk_indices = &self.pk_indices;
1667 let pk = (&value).project(pk_indices);
1668
1669 let key_bytes = self.serialize_pk(&pk);
1670 dispatch_value_indices!(&self.value_indices, [value], {
1671 self.row_store.insert(key_bytes, value)
1672 })
1673 }
1674
1675 pub fn delete(&mut self, old_value: impl Row) {
1678 let pk_indices = &self.pk_indices;
1679 let pk = (&old_value).project(pk_indices);
1680
1681 let key_bytes = self.serialize_pk(&pk);
1682 dispatch_value_indices!(&self.value_indices, [old_value], {
1683 self.row_store.delete(key_bytes, old_value)
1684 })
1685 }
1686
1687 pub fn update(&mut self, old_value: impl Row, new_value: impl Row) {
1689 let old_pk = (&old_value).project(self.pk_indices());
1690 let new_pk = (&new_value).project(self.pk_indices());
1691 debug_assert!(
1692 Row::eq(&old_pk, new_pk),
1693 "pk should not change: {old_pk:?} vs {new_pk:?}. {}",
1694 self.table_id
1695 );
1696
1697 let key_bytes = self.serialize_pk(&new_pk);
1698 dispatch_value_indices!(&self.value_indices, [old_value, new_value], {
1699 self.row_store.update(key_bytes, old_value, new_value)
1700 })
1701 }
1702
1703 pub fn write_record(&mut self, record: Record<impl Row>) {
1705 match record {
1706 Record::Insert { new_row } => self.insert(new_row),
1707 Record::Delete { old_row } => self.delete(old_row),
1708 Record::Update { old_row, new_row } => self.update(old_row, new_row),
1709 }
1710 }
1711
1712 fn fill_non_output_indices(&self, chunk: StreamChunk) -> StreamChunk {
1713 fill_non_output_indices(&self.i2o_mapping, &self.data_types, chunk)
1714 }
1715
1716 #[allow(clippy::disallowed_methods)]
1719 pub fn write_chunk(&mut self, chunk: StreamChunk) {
1720 let chunk = if IS_REPLICATED {
1721 self.fill_non_output_indices(chunk)
1722 } else {
1723 chunk
1724 };
1725
1726 let vnodes = self
1727 .distribution
1728 .compute_chunk_vnode(&chunk, &self.pk_indices);
1729
1730 for (idx, optional_row) in chunk.rows_with_holes().enumerate() {
1731 let Some((op, row)) = optional_row else {
1732 continue;
1733 };
1734 let pk = row.project(&self.pk_indices);
1735 let vnode = vnodes[idx];
1736 let key_bytes = serialize_pk_with_vnode(pk, &self.pk_serde, vnode);
1737 match op {
1738 Op::Insert | Op::UpdateInsert => {
1739 dispatch_value_indices!(&self.value_indices, [row], {
1740 self.row_store.insert(key_bytes, row);
1741 });
1742 }
1743 Op::Delete | Op::UpdateDelete => {
1744 dispatch_value_indices!(&self.value_indices, [row], {
1745 self.row_store.delete(key_bytes, row);
1746 });
1747 }
1748 }
1749 }
1750 }
1751
1752 pub fn update_watermark(&mut self, watermark: ScalarImpl) {
1759 trace!(table_id = %self.table_id, watermark = ?watermark, "update watermark");
1760 if let Some((direction, vnode_watermark, WatermarkSerdeType::PkPrefix)) =
1761 self.serialize_watermark(&watermark)
1762 {
1763 self.row_store
1764 .update_pending_watermark(direction, vnode_watermark);
1765 }
1766 self.pending_watermark = Some(watermark);
1767 }
1768
1769 pub fn get_committed_watermark(&self) -> Option<&ScalarImpl> {
1772 self.committed_watermark.as_ref()
1773 }
1774
1775 pub fn get_pending_watermark(&self) -> Option<&ScalarImpl> {
1778 self.pending_watermark.as_ref()
1779 }
1780
1781 pub async fn commit(
1782 &mut self,
1783 new_epoch: EpochPair,
1784 ) -> StreamExecutorResult<StateTablePostCommit<'_, S, SD, IS_REPLICATED>> {
1785 self.commit_inner(new_epoch, None).await
1786 }
1787
1788 #[cfg(test)]
1789 pub async fn commit_for_test(&mut self, new_epoch: EpochPair) -> StreamExecutorResult<()> {
1790 self.commit_assert_no_update_vnode_bitmap(new_epoch).await
1791 }
1792
1793 pub async fn commit_assert_no_update_vnode_bitmap(
1794 &mut self,
1795 new_epoch: EpochPair,
1796 ) -> StreamExecutorResult<()> {
1797 let post_commit = self.commit_inner(new_epoch, None).await?;
1798 post_commit.post_yield_barrier(None).await?;
1799 Ok(())
1800 }
1801
1802 pub async fn commit_may_switch_consistent_op(
1803 &mut self,
1804 new_epoch: EpochPair,
1805 op_consistency_level: StateTableOpConsistencyLevel,
1806 ) -> StreamExecutorResult<StateTablePostCommit<'_, S, SD, IS_REPLICATED>> {
1807 if self.op_consistency_level != op_consistency_level {
1808 if !cfg!(debug_assertions) {
1810 info!(
1811 ?new_epoch,
1812 prev_op_consistency_level = ?self.op_consistency_level,
1813 ?op_consistency_level,
1814 table_id = %self.table_id,
1815 "switch to new op consistency level"
1816 );
1817 }
1818 self.commit_inner(new_epoch, Some(op_consistency_level))
1819 .await
1820 } else {
1821 self.commit_inner(new_epoch, None).await
1822 }
1823 }
1824
1825 async fn commit_inner(
1826 &mut self,
1827 new_epoch: EpochPair,
1828 switch_consistent_op: Option<StateTableOpConsistencyLevel>,
1829 ) -> StreamExecutorResult<StateTablePostCommit<'_, S, SD, IS_REPLICATED>> {
1830 assert!(!self.on_post_commit);
1831 assert_eq!(
1832 self.epoch.expect("should only be called after init").curr,
1833 new_epoch.prev
1834 );
1835 if let Some(new_consistency_level) = switch_consistent_op {
1836 assert_ne!(self.op_consistency_level, new_consistency_level);
1837 self.op_consistency_level = new_consistency_level;
1838 }
1839 trace!(
1840 table_id = %self.table_id,
1841 epoch = ?self.epoch,
1842 "commit state table"
1843 );
1844
1845 let table_watermarks = self.commit_pending_watermark();
1846 self.row_store
1847 .seal_current_epoch(new_epoch.curr, table_watermarks, switch_consistent_op)
1848 .instrument_await(await_tree::span!(
1849 "state_table_commit table_id={} epoch={}",
1850 self.table_id,
1851 new_epoch.curr
1852 ))
1853 .await?;
1854 self.epoch = Some(new_epoch);
1855
1856 self.on_post_commit = true;
1857 Ok(StateTablePostCommit { inner: self })
1858 }
1859
1860 fn commit_pending_watermark(
1862 &mut self,
1863 ) -> Option<(WatermarkDirection, Vec<VnodeWatermark>, WatermarkSerdeType)> {
1864 let watermark = self.pending_watermark.take()?;
1865 trace!(table_id = %self.table_id, watermark = ?watermark, "state cleaning");
1866
1867 assert!(
1868 !self.pk_indices().is_empty(),
1869 "see pending watermark on empty pk"
1870 );
1871 let (direction, vnode_watermark, watermark_type) = self
1872 .serialize_watermark(&watermark)
1873 .expect("watermark serde should be initialized to commit watermark");
1874 trace!(table_id = %self.table_id, ?vnode_watermark, "table watermark");
1875
1876 self.row_store.pending_watermark = None;
1878 self.committed_watermark = Some(watermark);
1879 Some((direction, vec![vnode_watermark], watermark_type))
1880 }
1881
1882 fn serialize_watermark(
1885 &self,
1886 watermark: &ScalarImpl,
1887 ) -> Option<(WatermarkDirection, VnodeWatermark, WatermarkSerdeType)> {
1888 let (watermark_serializer, watermark_type) = self.watermark_serde.as_ref()?;
1889 let watermark_suffix =
1890 serialize_row(row::once(Some(watermark.clone())), watermark_serializer);
1891 let vnode_watermark = VnodeWatermark::new(
1892 self.vnodes().clone(),
1893 Bytes::copy_from_slice(watermark_suffix.as_ref()),
1894 );
1895 let order_type = watermark_serializer.get_order_types().get(0).unwrap();
1896 let direction = if order_type.is_ascending() {
1897 WatermarkDirection::Ascending
1898 } else {
1899 WatermarkDirection::Descending
1900 };
1901 Some((direction, vnode_watermark, *watermark_type))
1902 }
1903
1904 pub async fn try_flush(&mut self) -> StreamExecutorResult<()> {
1905 self.row_store.try_flush().await?;
1906 Ok(())
1907 }
1908}
1909
1910pub trait RowStream<'a>: Stream<Item = StreamExecutorResult<OwnedRow>> + 'a {}
1912impl<'a, S: Stream<Item = StreamExecutorResult<OwnedRow>> + 'a> RowStream<'a> for S {}
1913
1914pub trait KeyedRowStream<'a>: Stream<Item = StreamExecutorResult<KeyedRow<Bytes>>> + 'a {}
1915impl<'a, S: Stream<Item = StreamExecutorResult<KeyedRow<Bytes>>> + 'a> KeyedRowStream<'a> for S {}
1916
1917pub trait PkRowStream<'a, K>: Stream<Item = StreamExecutorResult<(K, OwnedRow)>> + 'a {}
1918impl<'a, K, S: Stream<Item = StreamExecutorResult<(K, OwnedRow)>> + 'a> PkRowStream<'a, K> for S {}
1919
1920pub type BoxedRowStream<'a> = BoxStream<'a, StreamExecutorResult<OwnedRow>>;
1921
1922pub trait FromVnodeBytes {
1923 fn from_vnode_bytes(vnode: VirtualNode, bytes: &Bytes) -> Self;
1924}
1925
1926impl FromVnodeBytes for Bytes {
1927 fn from_vnode_bytes(vnode: VirtualNode, bytes: &Bytes) -> Self {
1928 prefix_slice_with_vnode(vnode, bytes)
1929 }
1930}
1931
1932impl FromVnodeBytes for () {
1933 fn from_vnode_bytes(_vnode: VirtualNode, _bytes: &Bytes) -> Self {}
1934}
1935
1936impl<R, SD> StateTableFlushedSnapshotReader<R, SD>
1937where
1938 R: StateStoreRead,
1939 SD: ValueRowSerde,
1940{
1941 pub fn vnodes(&self) -> &Arc<Bitmap> {
1942 &self.vnodes
1943 }
1944
1945 pub async fn iter_with_vnode(
1947 &self,
1948 vnode: VirtualNode,
1949 pk_range: &(Bound<impl Row>, Bound<impl Row>),
1950 prefetch_options: PrefetchOptions,
1951 ) -> StreamExecutorResult<impl RowStream<'static>> {
1952 if let Some(m) = &self.metrics {
1953 m.iter_count.inc();
1954 }
1955
1956 let memcomparable_range = prefix_range_to_memcomparable(&self.pk_serde, pk_range);
1957 let iter = self
1958 .reader
1959 .iter(
1960 prefixed_range_with_vnode(memcomparable_range, vnode),
1961 ReadOptions {
1962 prefix_hint: None,
1963 prefetch_options,
1964 cache_policy: CachePolicy::Fill(Hint::Normal),
1965 },
1966 )
1967 .await?;
1968 let row_serde = self.row_serde.clone();
1969 Ok(iter
1970 .into_stream(move |(_key, value)| Ok(OwnedRow::new(row_serde.deserialize(value)?)))
1971 .map_err(Into::into))
1972 }
1973}
1974
1975impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
1977where
1978 S: StateStore,
1979 SD: ValueRowSerde,
1980{
1981 pub async fn iter_with_vnode(
1984 &self,
1985
1986 vnode: VirtualNode,
1990 pk_range: &(Bound<impl Row>, Bound<impl Row>),
1991 prefetch_options: PrefetchOptions,
1992 ) -> StreamExecutorResult<impl RowStream<'_>> {
1993 Ok(self
1994 .iter_kv_with_pk_range::<()>(pk_range, vnode, prefetch_options)
1995 .await?
1996 .map_ok(|(_, row)| {
1997 if IS_REPLICATED {
1998 row.project(&self.output_indices).into_owned_row()
1999 } else {
2000 row
2001 }
2002 }))
2003 }
2004
2005 pub async fn iter_keyed_row_with_vnode(
2006 &self,
2007 vnode: VirtualNode,
2008 pk_range: &(Bound<impl Row>, Bound<impl Row>),
2009 prefetch_options: PrefetchOptions,
2010 ) -> StreamExecutorResult<impl KeyedRowStream<'_>> {
2011 Ok(self
2012 .iter_kv_with_pk_range(pk_range, vnode, prefetch_options)
2013 .await?
2014 .map_ok(|(key, row)| KeyedRow::new(TableKey(key), row)))
2015 }
2016}
2017
2018impl<LS: LocalStateStore, SD: ValueRowSerde> StateTableRowStore<LS, SD> {
2019 async fn iter_kv<K: CopyFromSlice + FromVnodeBytes>(
2024 &self,
2025 vnode: VirtualNode,
2026 (start, end): (Bound<Bytes>, Bound<Bytes>),
2027 prefix_hint: Option<Bytes>,
2028 prefetch_options: PrefetchOptions,
2029 ) -> StreamExecutorResult<impl PkRowStream<'_, K>> {
2030 if let Some(m) = &self.metrics {
2031 m.iter_count.inc();
2032 }
2033 let (pruned_start, pruned_end, should_prune_entirely) = if let Some(stats) =
2035 &self.vnode_stats
2036 && let Some(vnode_stat) = stats.get(&vnode)
2037 {
2038 match vnode_stat.pruned_key_range(&start, &end) {
2039 Some((new_start, new_end)) => {
2040 if self.enable_state_table_vnode_stats_pruning {
2041 (new_start, new_end, false)
2042 } else {
2043 (start, end, false)
2045 }
2046 }
2047 None => {
2048 if let Some(m) = &self.metrics {
2049 m.iter_vnode_pruned_count.inc();
2050 }
2051 (start.clone(), end.clone(), true)
2053 }
2054 }
2055 } else {
2056 (start, end, false)
2057 };
2058
2059 if should_prune_entirely && self.enable_state_table_vnode_stats_pruning {
2060 return Ok(futures::future::Either::Left(futures::stream::empty()));
2061 }
2062
2063 let table_id = self.table_id;
2064 let inspect_fn = move |result: &StreamExecutorResult<(K, OwnedRow)>| {
2065 if should_prune_entirely && result.is_ok() {
2067 tracing::warn!(
2068 table_id = %table_id,
2069 "vnode stats pruning dry run fails for iter. This will not affect correctness."
2070 );
2071 }
2072 };
2073
2074 if let Some(rows) = &self.all_rows {
2075 return Ok(futures::future::Either::Right(
2076 futures::future::Either::Left(
2077 futures::stream::iter(
2078 rows.get(&vnode)
2079 .expect("covered vnode")
2080 .range((pruned_start, pruned_end))
2081 .map(move |(key, value)| {
2082 Ok((K::from_vnode_bytes(vnode, key), value.clone()))
2083 }),
2084 )
2085 .inspect(inspect_fn),
2086 ),
2087 ));
2088 }
2089 let read_options = ReadOptions {
2090 prefix_hint,
2091 prefetch_options,
2092 cache_policy: CachePolicy::Fill(Hint::Normal),
2093 };
2094 let mut key_range = prefixed_range_with_vnode((pruned_start, pruned_end), vnode);
2095 self.narrow_by_pending_watermark(&mut key_range);
2096
2097 Ok(futures::future::Either::Right(
2098 futures::future::Either::Right(
2099 deserialize_keyed_row_stream(
2100 self.state_store.iter(key_range, read_options).await?,
2101 &*self.row_serde,
2102 )
2103 .inspect(inspect_fn),
2104 ),
2105 ))
2106 }
2107
2108 async fn rev_iter_kv<K: CopyFromSlice + FromVnodeBytes>(
2109 &self,
2110 vnode: VirtualNode,
2111 (start, end): (Bound<Bytes>, Bound<Bytes>),
2112 prefix_hint: Option<Bytes>,
2113 prefetch_options: PrefetchOptions,
2114 ) -> StreamExecutorResult<impl PkRowStream<'_, K>> {
2115 if let Some(m) = &self.metrics {
2116 m.iter_count.inc();
2117 }
2118 let (pruned_start, pruned_end, should_prune_entirely) = if let Some(stats) =
2120 &self.vnode_stats
2121 && let Some(vnode_stat) = stats.get(&vnode)
2122 {
2123 match vnode_stat.pruned_key_range(&start, &end) {
2124 Some((new_start, new_end)) => {
2125 if self.enable_state_table_vnode_stats_pruning {
2126 (new_start, new_end, false)
2127 } else {
2128 (start, end, false)
2130 }
2131 }
2132 None => {
2133 if let Some(m) = &self.metrics {
2134 m.iter_vnode_pruned_count.inc();
2135 }
2136 (start, end, true)
2138 }
2139 }
2140 } else {
2141 (start, end, false)
2142 };
2143
2144 if should_prune_entirely && self.enable_state_table_vnode_stats_pruning {
2145 return Ok(futures::future::Either::Left(futures::stream::empty()));
2146 }
2147
2148 let table_id = self.table_id;
2149 let inspect_fn = move |result: &StreamExecutorResult<(K, OwnedRow)>| {
2150 if should_prune_entirely && result.is_ok() {
2152 tracing::warn!(
2153 table_id = %table_id,
2154 "vnode stats pruning dry run fails for rev_iter. This will not affect correctness."
2155 );
2156 }
2157 };
2158
2159 if let Some(rows) = &self.all_rows {
2160 return Ok(futures::future::Either::Right(
2161 futures::future::Either::Left(
2162 futures::stream::iter(
2163 rows.get(&vnode)
2164 .expect("covered vnode")
2165 .range((pruned_start, pruned_end))
2166 .rev()
2167 .map(move |(key, value)| {
2168 Ok((K::from_vnode_bytes(vnode, key), value.clone()))
2169 }),
2170 )
2171 .inspect(inspect_fn),
2172 ),
2173 ));
2174 }
2175 let read_options = ReadOptions {
2176 prefix_hint,
2177 prefetch_options,
2178 cache_policy: CachePolicy::Fill(Hint::Normal),
2179 };
2180 let mut key_range = prefixed_range_with_vnode((pruned_start, pruned_end), vnode);
2181 self.narrow_by_pending_watermark(&mut key_range);
2182
2183 Ok(futures::future::Either::Right(
2184 futures::future::Either::Right(
2185 deserialize_keyed_row_stream(
2186 self.state_store.rev_iter(key_range, read_options).await?,
2187 &*self.row_serde,
2188 )
2189 .inspect(inspect_fn),
2190 ),
2191 ))
2192 }
2193}
2194
2195impl<S, SD, const IS_REPLICATED: bool> StateTableInner<S, SD, IS_REPLICATED>
2196where
2197 S: StateStore,
2198 SD: ValueRowSerde,
2199{
2200 pub async fn iter_with_prefix(
2204 &self,
2205 pk_prefix: impl Row,
2206 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2207 prefetch_options: PrefetchOptions,
2208 ) -> StreamExecutorResult<impl RowStream<'_>> {
2209 let stream = self.iter_with_prefix_inner::<false, ()>(pk_prefix, sub_range, prefetch_options)
2210 .await?;
2211 Ok(stream.map_ok(|(_, row)| {
2212 if IS_REPLICATED {
2213 row.project(&self.output_indices).into_owned_row()
2214 } else {
2215 row
2216 }
2217 }))
2218 }
2219
2220 pub async fn iter_with_prefix_respecting_watermark(
2226 &self,
2227 pk_prefix: impl Row,
2228 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2229 prefetch_options: PrefetchOptions,
2230 ) -> StreamExecutorResult<BoxedRowStream<'_>> {
2231 let vnode = self.compute_prefix_vnode(&pk_prefix);
2232 let Some(clean_watermark_index) = self.clean_watermark_index else {
2233 return self
2234 .iter_with_prefix(pk_prefix, sub_range, prefetch_options)
2235 .await
2236 .map(|s| s.boxed());
2237 };
2238 let Some((watermark_serde, watermark_type)) = &self.watermark_serde else {
2239 return Err(StreamExecutorError::from(anyhow!(
2240 "Missing watermark serde"
2241 )));
2242 };
2243 if matches!(watermark_type, WatermarkSerdeType::PkPrefix) {
2245 return self
2246 .iter_with_prefix(pk_prefix, sub_range, prefetch_options)
2247 .await
2248 .map(|s| s.boxed());
2249 }
2250
2251 let watermark_bytes = self.row_store.state_store.get_table_watermark(vnode);
2252 let Some(watermark_bytes) = watermark_bytes else {
2253 return self
2254 .iter_with_prefix(pk_prefix, sub_range, prefetch_options)
2255 .await
2256 .map(|s| s.boxed());
2257 };
2258 let watermark_row = watermark_serde.deserialize(&watermark_bytes)?;
2259 if watermark_row.len() != 1 {
2260 return Err(StreamExecutorError::from(format!(
2261 "Watermark row should have exactly 1 column, got {}",
2262 watermark_row.len()
2263 )));
2264 }
2265 let watermark_value = watermark_row[0].clone();
2266 if watermark_value.is_none() {
2268 return Err(StreamExecutorError::from(anyhow!(
2269 "Watermark cannot be NULL"
2270 )));
2271 }
2272 let order_type = watermark_serde.get_order_types().get(0).ok_or_else(|| {
2273 StreamExecutorError::from(anyhow!(
2274 "Watermark serde should have at least one order type"
2275 ))
2276 })?;
2277
2278 let direction = if order_type.is_ascending() {
2279 WatermarkDirection::Ascending
2280 } else {
2281 WatermarkDirection::Descending
2282 };
2283 let clean_watermark_index_in_pk = self
2284 .pk_indices
2285 .iter()
2286 .position(|&i| i == clean_watermark_index);
2287 let clean_watermark_index_in_value = match &self.value_indices {
2288 Some(value_indices) => value_indices
2289 .iter()
2290 .position(|idx| *idx == clean_watermark_index)
2291 .ok_or_else(|| {
2292 StreamExecutorError::from(anyhow!(
2293 "clean watermark column index {} is not included in table value indices {:?}",
2294 clean_watermark_index,
2295 value_indices
2296 ))
2297 })?,
2298 None => clean_watermark_index,
2299 };
2300
2301 let stream = self
2302 .iter_with_prefix_inner::<false, Bytes>(pk_prefix, sub_range, prefetch_options)
2303 .await?
2304 .try_filter_map(move |(pk, row)| {
2305 let should_filter = match watermark_type {
2306 WatermarkSerdeType::PkPrefix => unreachable!(),
2307 WatermarkSerdeType::NonPkPrefix => {
2308 let table_key = TableKey(pk);
2309 let (vnode, key) = table_key.split_vnode();
2310 let pk_cols = self.pk_serde
2311 .deserialize(key)
2312 .unwrap_or_else(|e| {
2313 panic!("Failed to deserialize table {} vnode {:?} key {:?} error: {:?}", self.table_id(), vnode, key, e.as_report());
2314 });
2315 direction.datum_filter_by_watermark(
2316 pk_cols.datum_at(clean_watermark_index_in_pk.unwrap()),
2317 &watermark_value,
2318 *order_type,
2319 )
2320 },
2321 WatermarkSerdeType::Value => {
2322 direction.datum_filter_by_watermark(
2323 row.datum_at(clean_watermark_index_in_value),
2324 &watermark_value,
2325 *order_type,
2326 )
2327 }
2328 };
2329 if should_filter {
2330 ready(Ok(None))
2331 } else {
2332 ready(Ok(Some(row)))
2333 }
2334 });
2335 Ok(stream.boxed())
2336 }
2337
2338 pub async fn get_from_one_row_table(&self) -> StreamExecutorResult<Option<OwnedRow>> {
2340 let sub_range: &(Bound<OwnedRow>, Bound<OwnedRow>) = &(Unbounded, Unbounded);
2341 let stream = self
2342 .iter_with_prefix(row::empty(), sub_range, Default::default())
2343 .await?;
2344 pin_mut!(stream);
2345
2346 if let Some(res) = stream.next().await {
2347 let value = res?.into_owned_row();
2348 assert!(stream.next().await.is_none());
2349 Ok(Some(value))
2350 } else {
2351 Ok(None)
2352 }
2353 }
2354
2355 pub async fn get_from_one_value_table(&self) -> StreamExecutorResult<Option<ScalarImpl>> {
2360 Ok(self
2361 .get_from_one_row_table()
2362 .await?
2363 .and_then(|row| row[0].clone()))
2364 }
2365
2366 pub async fn iter_keyed_row_with_prefix(
2367 &self,
2368 pk_prefix: impl Row,
2369 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2370 prefetch_options: PrefetchOptions,
2371 ) -> StreamExecutorResult<impl KeyedRowStream<'_>> {
2372 Ok(
2373 self.iter_with_prefix_inner::<false, Bytes>(pk_prefix, sub_range, prefetch_options)
2374 .await?.map_ok(|(key, row)| KeyedRow::new(TableKey(key), row)),
2375 )
2376 }
2377
2378 pub async fn rev_iter_keyed_row_with_prefix(
2379 &self,
2380 pk_prefix: impl Row,
2381 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2382 prefetch_options: PrefetchOptions,
2383 ) -> StreamExecutorResult<impl KeyedRowStream<'_>> {
2384 Ok(
2385 self.iter_with_prefix_inner::<true, Bytes>(pk_prefix, sub_range, prefetch_options)
2386 .await?.map_ok(|(key, row)| KeyedRow::new(TableKey(key), row)),
2387 )
2388 }
2389
2390 pub async fn rev_iter_with_prefix(
2392 &self,
2393 pk_prefix: impl Row,
2394 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2395 prefetch_options: PrefetchOptions,
2396 ) -> StreamExecutorResult<impl RowStream<'_>> {
2397 Ok(
2398 self.iter_with_prefix_inner::<true, ()>(pk_prefix, sub_range, prefetch_options)
2399 .await?.map_ok(|(_, row)| row),
2400 )
2401 }
2402
2403 async fn iter_with_prefix_inner<const REVERSE: bool, K: CopyFromSlice + FromVnodeBytes>(
2404 &self,
2405 pk_prefix: impl Row,
2406 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2407 prefetch_options: PrefetchOptions,
2408 ) -> StreamExecutorResult<impl PkRowStream<'_, K>> {
2409 let prefix_serializer = self.pk_serde.prefix(pk_prefix.len());
2410 let encoded_prefix = serialize_pk(&pk_prefix, &prefix_serializer);
2411
2412 let vnode = self.compute_prefix_vnode(&pk_prefix);
2416
2417 let pk_prefix_indices = &self.pk_indices[..pk_prefix.len()];
2419 if self.prefix_hint_len != 0 && !IS_REPLICATED {
2420 debug_assert_eq!(self.prefix_hint_len, pk_prefix.len());
2421 }
2422 let prefix_hint = {
2423 if should_calculate_prefix_hint(self.prefix_hint_len, pk_prefix.len(), true) {
2424 let encoded_prefix_len = self
2425 .pk_serde
2426 .deserialize_prefix_len(&encoded_prefix, self.prefix_hint_len)?;
2427
2428 Some(Bytes::copy_from_slice(
2429 &encoded_prefix[..encoded_prefix_len],
2430 ))
2431 } else {
2432 None
2433 }
2434 };
2435
2436 trace!(
2437 table_id = %self.table_id(),
2438 ?prefix_hint, ?pk_prefix,
2439 ?pk_prefix_indices,
2440 iter_direction = if REVERSE { "reverse" } else { "forward" },
2441 "storage_iter_with_prefix"
2442 );
2443
2444 let memcomparable_range =
2445 prefix_and_sub_range_to_memcomparable(&self.pk_serde, sub_range, pk_prefix);
2446
2447 Ok(if REVERSE {
2448 futures::future::Either::Left(
2449 self.row_store
2450 .rev_iter_kv(vnode, memcomparable_range, prefix_hint, prefetch_options)
2451 .await?,
2452 )
2453 } else {
2454 futures::future::Either::Right(
2455 self.row_store
2456 .iter_kv(vnode, memcomparable_range, prefix_hint, prefetch_options)
2457 .await?,
2458 )
2459 })
2460 }
2461
2462 async fn iter_kv_with_pk_range<'a, K: CopyFromSlice + FromVnodeBytes>(
2465 &'a self,
2466 pk_range: &(Bound<impl Row>, Bound<impl Row>),
2467 vnode: VirtualNode,
2471 prefetch_options: PrefetchOptions,
2472 ) -> StreamExecutorResult<impl PkRowStream<'a, K>> {
2473 let memcomparable_range = prefix_range_to_memcomparable(&self.pk_serde, pk_range);
2474
2475 self.row_store
2477 .iter_kv(vnode, memcomparable_range, None, prefetch_options)
2478 .await
2479 }
2480}
2481
2482fn deserialize_keyed_row_stream<'a, K: CopyFromSlice>(
2483 iter: impl StateStoreIter + 'a,
2484 deserializer: &'a impl ValueRowSerde,
2485) -> impl PkRowStream<'a, K> {
2486 iter.into_stream(move |(key, value)| {
2487 Ok((
2488 K::copy_from_slice(key.user_key.table_key.as_ref()),
2489 deserializer.deserialize(value).map(OwnedRow::new)?,
2490 ))
2491 })
2492 .map_err(Into::into)
2493}
2494
2495pub fn prefix_range_to_memcomparable(
2496 pk_serde: &OrderedRowSerde,
2497 range: &(Bound<impl Row>, Bound<impl Row>),
2498) -> (Bound<Bytes>, Bound<Bytes>) {
2499 (
2500 start_range_to_memcomparable(pk_serde, &range.0),
2501 end_range_to_memcomparable(pk_serde, &range.1, None),
2502 )
2503}
2504
2505fn prefix_and_sub_range_to_memcomparable(
2506 pk_serde: &OrderedRowSerde,
2507 sub_range: &(Bound<impl Row>, Bound<impl Row>),
2508 pk_prefix: impl Row,
2509) -> (Bound<Bytes>, Bound<Bytes>) {
2510 let (range_start, range_end) = sub_range;
2511 let prefix_serializer = pk_serde.prefix(pk_prefix.len());
2512 let serialized_pk_prefix = serialize_pk(&pk_prefix, &prefix_serializer);
2513 let start_range = match range_start {
2514 Included(start_range) => Bound::Included(Either::Left((&pk_prefix).chain(start_range))),
2515 Excluded(start_range) => Bound::Excluded(Either::Left((&pk_prefix).chain(start_range))),
2516 Unbounded => Bound::Included(Either::Right(&pk_prefix)),
2517 };
2518 let end_range = match range_end {
2519 Included(end_range) => Bound::Included((&pk_prefix).chain(end_range)),
2520 Excluded(end_range) => Bound::Excluded((&pk_prefix).chain(end_range)),
2521 Unbounded => Unbounded,
2522 };
2523 (
2524 start_range_to_memcomparable(pk_serde, &start_range),
2525 end_range_to_memcomparable(pk_serde, &end_range, Some(serialized_pk_prefix)),
2526 )
2527}
2528
2529fn start_range_to_memcomparable<R: Row>(
2530 pk_serde: &OrderedRowSerde,
2531 bound: &Bound<R>,
2532) -> Bound<Bytes> {
2533 let serialize_pk_prefix = |pk_prefix: &R| {
2534 let prefix_serializer = pk_serde.prefix(pk_prefix.len());
2535 serialize_pk(pk_prefix, &prefix_serializer)
2536 };
2537 match bound {
2538 Unbounded => Unbounded,
2539 Included(r) => {
2540 let serialized = serialize_pk_prefix(r);
2541
2542 Included(serialized)
2543 }
2544 Excluded(r) => {
2545 let serialized = serialize_pk_prefix(r);
2546
2547 start_bound_of_excluded_prefix(&serialized)
2548 }
2549 }
2550}
2551
2552fn end_range_to_memcomparable<R: Row>(
2553 pk_serde: &OrderedRowSerde,
2554 bound: &Bound<R>,
2555 serialized_pk_prefix: Option<Bytes>,
2556) -> Bound<Bytes> {
2557 let serialize_pk_prefix = |pk_prefix: &R| {
2558 let prefix_serializer = pk_serde.prefix(pk_prefix.len());
2559 serialize_pk(pk_prefix, &prefix_serializer)
2560 };
2561 match bound {
2562 Unbounded => match serialized_pk_prefix {
2563 Some(serialized_pk_prefix) => end_bound_of_prefix(&serialized_pk_prefix),
2564 None => Unbounded,
2565 },
2566 Included(r) => {
2567 let serialized = serialize_pk_prefix(r);
2568 end_bound_of_prefix(&serialized)
2570 }
2571 Excluded(r) => {
2572 let serialized = serialize_pk_prefix(r);
2573 Excluded(serialized)
2574 }
2575 }
2576}
2577
2578fn fill_non_output_indices(
2579 i2o_mapping: &ColIndexMapping,
2580 data_types: &[DataType],
2581 chunk: StreamChunk,
2582) -> StreamChunk {
2583 let (ops, columns, vis) = chunk.into_inner();
2584 let capacity = vis.len();
2585 let mut full_columns = Vec::with_capacity(data_types.len());
2586 for (i, data_type) in data_types.iter().enumerate() {
2587 if let Some(j) = i2o_mapping.try_map(i) {
2588 full_columns.push(columns[j].clone());
2589 } else {
2590 let mut column_builder = ArrayImplBuilder::with_type(capacity, data_type.clone());
2591 column_builder.append_n_null(capacity);
2592 let column: ArrayRef = column_builder.finish().into();
2593 full_columns.push(column)
2594 }
2595 }
2596 let data_chunk = DataChunk::new(full_columns, vis);
2597 StreamChunk::from_parts(ops, data_chunk)
2598}
2599
2600#[cfg(test)]
2601mod tests {
2602 use std::fmt::Debug;
2603
2604 use expect_test::{Expect, expect};
2605
2606 use super::*;
2607
2608 fn check(actual: impl Debug, expect: Expect) {
2609 let actual = format!("{:#?}", actual);
2610 expect.assert_eq(&actual);
2611 }
2612
2613 #[test]
2614 fn test_fill_non_output_indices() {
2615 let data_types = vec![DataType::Int32, DataType::Int32, DataType::Int32];
2616 let replicated_chunk = [OwnedRow::new(vec![
2617 Some(222_i32.into()),
2618 Some(2_i32.into()),
2619 ])];
2620 let replicated_chunk = StreamChunk::from_parts(
2621 vec![Op::Insert],
2622 DataChunk::from_rows(&replicated_chunk, &[DataType::Int32, DataType::Int32]),
2623 );
2624 let i2o_mapping = ColIndexMapping::new(vec![Some(1), None, Some(0)], 2);
2625 let filled_chunk = fill_non_output_indices(&i2o_mapping, &data_types, replicated_chunk);
2626 check(
2627 filled_chunk,
2628 expect![[r#"
2629 StreamChunk { cardinality: 1, capacity: 1, data:
2630 +---+---+---+-----+
2631 | + | 2 | | 222 |
2632 +---+---+---+-----+
2633 }"#]],
2634 );
2635 }
2636
2637 #[test]
2638 fn test_fill_non_output_indices_with_invisible_rows() {
2639 let data_types = vec![DataType::Int32, DataType::Int32, DataType::Int32];
2640 let replicated_chunk = [
2641 OwnedRow::new(vec![Some(222_i32.into()), Some(2_i32.into())]),
2642 OwnedRow::new(vec![Some(333_i32.into()), Some(3_i32.into())]),
2643 ];
2644 let (columns, _) =
2645 DataChunk::from_rows(&replicated_chunk, &[DataType::Int32, DataType::Int32])
2646 .into_parts();
2647 let replicated_chunk = StreamChunk::with_visibility(
2648 vec![Op::Insert, Op::Insert],
2649 columns,
2650 Bitmap::from_iter([false, false]),
2651 );
2652 let i2o_mapping = ColIndexMapping::new(vec![Some(1), None, Some(0)], 2);
2653 let filled_chunk = fill_non_output_indices(&i2o_mapping, &data_types, replicated_chunk);
2654 check(
2655 filled_chunk,
2656 expect![[r#"
2657 StreamChunk { cardinality: 0, capacity: 2, data:
2658 (empty)
2659 }"#]],
2660 );
2661 }
2662}