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