mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-08-12 09:19:44 +00:00
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:
+27
-6
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 = "\
|
||||
+-------+-------+---------+---------------------+
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 = "\
|
||||
+-------+---------+---------------------+
|
||||
|
||||
@@ -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 = "\
|
||||
+-------+---------+---------------------+
|
||||
|
||||
@@ -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 = "\
|
||||
+-------+---------+---------------------+
|
||||
|
||||
@@ -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 = "\
|
||||
+-------+---------+---------------------+
|
||||
|
||||
@@ -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 = "\
|
||||
+-------+---------+---------------------+
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user