feat: Adds RegionScanner trait (#3948)

* feat: define region scanner

* feat: single partition scanner

* feat: use single partition scanner

* feat: implement ExecutionPlan wip

* feat: mito engine returns single partition scanner

* feat: implement DisplayAs for region server

* feat: dummy table provider use handle_partitioned_query()

* test: update sqlness test

* feat: table provider use ReadFromRegion

* refactor: remove StreamScanAdapter

* chore: update lock

* style: fix clippy

* refactor: remove handle_query from the RegionEngine trait

* chore: address CR comments

* refactor: rename methods

* refactor: rename ReadFromRegion to RegionScanExec
This commit is contained in:
Yingwen
2024-05-20 19:52:00 +08:00
committed by GitHub
parent 19543f9819
commit 179c8c716c
32 changed files with 371 additions and 209 deletions
+27 -6
View File
@@ -62,7 +62,7 @@ use object_store::manager::ObjectStoreManagerRef;
use snafu::{ensure, OptionExt, ResultExt};
use store_api::logstore::LogStore;
use store_api::metadata::RegionMetadataRef;
use store_api::region_engine::{RegionEngine, RegionRole, SetReadonlyResponse};
use store_api::region_engine::{RegionEngine, RegionRole, RegionScannerRef, SetReadonlyResponse};
use store_api::region_request::{AffectedRows, RegionRequest};
use store_api::storage::{RegionId, ScanRequest};
use tokio::sync::oneshot;
@@ -115,11 +115,35 @@ impl MitoEngine {
Ok(region.region_usage().await)
}
/// Handle substrait query and return a stream of record batches
#[tracing::instrument(skip_all)]
pub async fn scan_to_stream(
&self,
region_id: RegionId,
request: ScanRequest,
) -> std::result::Result<SendableRecordBatchStream, BoxedError> {
self.scanner(region_id, request)
.map_err(BoxedError::new)?
.scan()
.await
.map_err(BoxedError::new)
}
/// Returns a scanner to scan for `request`.
fn scanner(&self, region_id: RegionId, request: ScanRequest) -> Result<Scanner> {
self.scan_region(region_id, request)?.scanner()
}
/// Returns a region scanner to scan the region for `request`.
async fn region_scanner(
&self,
region_id: RegionId,
request: ScanRequest,
) -> Result<RegionScannerRef> {
let scanner = self.scanner(region_id, request)?;
scanner.region_scanner().await
}
/// Scans a region.
fn scan_region(&self, region_id: RegionId, request: ScanRequest) -> Result<ScanRegion> {
self.inner.handle_query(region_id, request)
@@ -312,16 +336,13 @@ impl RegionEngine for MitoEngine {
.map_err(BoxedError::new)
}
/// Handle substrait query and return a stream of record batches
#[tracing::instrument(skip_all)]
async fn handle_query(
&self,
region_id: RegionId,
request: ScanRequest,
) -> std::result::Result<SendableRecordBatchStream, BoxedError> {
self.scanner(region_id, request)
.map_err(BoxedError::new)?
.scan()
) -> Result<RegionScannerRef, BoxedError> {
self.region_scanner(region_id, request)
.await
.map_err(BoxedError::new)
}
+1 -1
View File
@@ -245,7 +245,7 @@ async fn test_put_after_alter() {
| | b | 2.0 | 1970-01-01T00:00:02 |
+-------+-------+---------+---------------------+";
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
assert_eq!(expected, batches.pretty_print().unwrap());
}
+2 -2
View File
@@ -63,7 +63,7 @@ async fn test_append_mode_write_query() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -183,7 +183,7 @@ async fn test_append_mode_compaction() {
// Reopens the region.
reopen_region(&engine, region_id, region_dir, false, region_opts).await;
let stream = engine
.handle_query(region_id, ScanRequest::default())
.scan_to_stream(region_id, ScanRequest::default())
.await
.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
+9 -9
View File
@@ -128,7 +128,7 @@ async fn test_region_replay() {
assert_eq!(0, result.affected_rows);
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
assert_eq!(42, batches.iter().map(|b| b.num_rows()).sum::<usize>());
@@ -166,7 +166,7 @@ async fn test_write_query_region() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -227,7 +227,7 @@ async fn test_different_order() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+-------+---------+---------+---------------------+
@@ -289,7 +289,7 @@ async fn test_different_order_and_type() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+-------+---------+---------+---------------------+
@@ -341,7 +341,7 @@ async fn test_put_delete() {
delete_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -383,7 +383,7 @@ async fn test_delete_not_null_fields() {
delete_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -398,7 +398,7 @@ async fn test_delete_not_null_fields() {
// Reopen and scan again.
reopen_region(&engine, region_id, region_dir, false, HashMap::new()).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
assert_eq!(expected, batches.pretty_print().unwrap());
}
@@ -447,7 +447,7 @@ async fn test_put_overwrite() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -688,7 +688,7 @@ async fn test_cache_null_primary_key() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+-------+---------+---------------------+
+3 -3
View File
@@ -104,7 +104,7 @@ async fn test_catchup_with_last_entry_id() {
// Scans
let request = ScanRequest::default();
let stream = follower_engine
.handle_query(region_id, request)
.scan_to_stream(region_id, request)
.await
.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
@@ -264,7 +264,7 @@ async fn test_catchup_without_last_entry_id() {
let request = ScanRequest::default();
let stream = follower_engine
.handle_query(region_id, request)
.scan_to_stream(region_id, request)
.await
.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
@@ -367,7 +367,7 @@ async fn test_catchup_with_manifest_update() {
let request = ScanRequest::default();
let stream = follower_engine
.handle_query(region_id, request)
.scan_to_stream(region_id, request)
.await
.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
+1 -1
View File
@@ -231,7 +231,7 @@ async fn test_engine_create_with_memtable_opts() {
put_rows(&engine, region_id, rows).await;
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
+1 -1
View File
@@ -69,7 +69,7 @@ async fn test_scan_without_filtering_deleted() {
// scan
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
+2 -2
View File
@@ -276,7 +276,7 @@ async fn test_open_region_skip_wal_replay() {
.unwrap();
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -305,7 +305,7 @@ async fn test_open_region_skip_wal_replay() {
.unwrap();
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
+1 -1
View File
@@ -57,7 +57,7 @@ async fn scan_in_parallel(
.unwrap();
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
+1 -1
View File
@@ -79,7 +79,7 @@ async fn test_scan_projection() {
output_ordering: None,
limit: None,
};
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
+3 -3
View File
@@ -53,7 +53,7 @@ async fn check_prune_row_groups(expr: DfExpr, expected: &str) {
flush_region(&engine, region_id, Some(5)).await;
let stream = engine
.handle_query(
.scan_to_stream(
region_id,
ScanRequest {
filters: vec![Expr::from(expr)],
@@ -186,7 +186,7 @@ async fn test_prune_memtable() {
.await;
let stream = engine
.handle_query(
.scan_to_stream(
region_id,
ScanRequest {
filters: vec![time_range_expr(0, 20)],
@@ -238,7 +238,7 @@ async fn test_prune_memtable_complex_expr() {
let filters = vec![time_range_expr(4, 7), Expr::from(col("tag_0").lt(lit("6")))];
let stream = engine
.handle_query(
.scan_to_stream(
region_id,
ScanRequest {
filters,
+5 -5
View File
@@ -55,7 +55,7 @@ async fn test_engine_truncate_region_basic() {
// Scan the region.
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -75,7 +75,7 @@ async fn test_engine_truncate_region_basic() {
// Scan the region.
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "++\n++";
assert_eq!(expected, batches.pretty_print().unwrap());
@@ -104,7 +104,7 @@ async fn test_engine_put_data_after_truncate() {
// Scan the region
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -131,7 +131,7 @@ async fn test_engine_put_data_after_truncate() {
// Scan the region.
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "\
+-------+---------+---------------------+
@@ -261,7 +261,7 @@ async fn test_engine_truncate_reopen() {
// Scan the region.
let request = ScanRequest::default();
let stream = engine.handle_query(region_id, request).await.unwrap();
let stream = engine.scan_to_stream(region_id, request).await.unwrap();
let batches = RecordBatches::try_collect(stream).await.unwrap();
let expected = "++\n++";
assert_eq!(expected, batches.pretty_print().unwrap());
+9
View File
@@ -20,6 +20,7 @@ use std::time::Instant;
use common_recordbatch::SendableRecordBatchStream;
use common_telemetry::{debug, error, warn};
use common_time::range::TimestampRange;
use store_api::region_engine::{RegionScannerRef, SinglePartitionScanner};
use store_api::storage::ScanRequest;
use table::predicate::{Predicate, TimeRangePredicateBuilder};
use tokio::sync::{mpsc, Semaphore};
@@ -57,6 +58,14 @@ impl Scanner {
Scanner::Unordered(unordered_scan) => unordered_scan.build_stream().await,
}
}
/// Returns a [RegionScanner] to scan the region.
pub(crate) async fn region_scanner(&self) -> Result<RegionScannerRef> {
let stream = self.scan().await?;
let scanner = SinglePartitionScanner::new(stream);
Ok(Arc::new(scanner))
}
}
#[cfg(test)]
+8 -8
View File
@@ -198,6 +198,14 @@ impl UnorderedScan {
}
}
#[cfg(test)]
impl UnorderedScan {
/// Returns the input.
pub(crate) fn input(&self) -> &ScanInput {
&self.input
}
}
/// Metrics for [UnorderedScan].
#[derive(Debug, Default)]
struct Metrics {
@@ -216,11 +224,3 @@ struct Metrics {
/// Number of rows returned.
num_rows: usize,
}
#[cfg(test)]
impl UnorderedScan {
/// Returns the input.
pub(crate) fn input(&self) -> &ScanInput {
&self.input
}
}