feat: add support for TWCS time window hints in insert operations (#6823)

* feat: Add support for TWCS time window hints in insert operations

Signed-off-by: WenyXu <wenymedia@gmail.com>

* feat: set system events table time window to 1d

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
This commit is contained in:
Weny Xu
2025-08-26 18:52:00 +08:00
committed by GitHub
parent 8894cb5406
commit 3d1a4b56a4
6 changed files with 136 additions and 7 deletions

View File

@@ -42,6 +42,7 @@ async fn query_and_expect(instance: &Instance, sql: &str, expected: &str) {
#[cfg(test)]
mod test {
use std::collections::HashMap;
use std::sync::Arc;
use api::v1::column::Values;
use api::v1::column_data_type_extension::TypeExt;
@@ -60,17 +61,24 @@ mod test {
use common_meta::rpc::router::region_distribution;
use common_query::Output;
use common_recordbatch::RecordBatches;
use common_test_util::recordbatch::check_output_stream;
use frontend::instance::Instance;
use query::parser::QueryLanguageParser;
use query::query_engine::DefaultSerializer;
use rstest::rstest;
use rstest_reuse::apply;
use servers::query_handler::grpc::GrpcQueryHandler;
use session::context::QueryContext;
use session::context::{QueryContext, QueryContextBuilder};
use store_api::mito_engine_options::TWCS_TIME_WINDOW;
use store_api::storage::RegionId;
use substrait::{DFLogicalSubstraitConvertor, SubstraitPlan};
use super::*;
use crate::standalone::GreptimeDbStandaloneBuilder;
use crate::tests;
use crate::tests::test_util::{
both_instances_cases, distributed, execute_sql, standalone, MockInstance,
};
use crate::tests::MockDistributedInstance;
#[tokio::test(flavor = "multi_thread")]
@@ -1159,4 +1167,92 @@ CREATE TABLE {table_name} (
+---+------+---------------------+";
assert_eq!(recordbatches.pretty_print().unwrap(), expected);
}
#[apply(both_instances_cases)]
async fn test_extra_external_table_options(instance: Arc<dyn MockInstance>) {
common_telemetry::init_default_ut_logging();
let frontend = instance.frontend();
let instance = frontend.as_ref();
let insert = InsertRequest {
table_name: "auto_created_table".to_string(),
columns: vec![
Column {
column_name: "a".to_string(),
values: Some(Values {
i32_values: vec![4, 6],
..Default::default()
}),
null_mask: vec![2],
semantic_type: SemanticType::Field as i32,
datatype: ColumnDataType::Int32 as i32,
..Default::default()
},
Column {
column_name: "c".to_string(),
values: Some(Values {
string_values: vec![
r#"{ "id": 1, "name": "Alice", "age": 30, "active": true }"#
.to_string(),
r#"{ "id": 2, "name": "Bob", "balance": 1234.56, "active": false }"#
.to_string(),
],
..Default::default()
}),
null_mask: vec![2],
semantic_type: SemanticType::Field as i32,
datatype: ColumnDataType::Json as i32,
..Default::default()
},
Column {
column_name: "ts".to_string(),
values: Some(Values {
timestamp_millisecond_values: vec![
1672557975000,
1672557976000,
1672557977000,
],
..Default::default()
}),
semantic_type: SemanticType::Timestamp as i32,
datatype: ColumnDataType::TimestampMillisecond as i32,
..Default::default()
},
],
row_count: 3,
};
let request = Request::Inserts(InsertRequests {
inserts: vec![insert],
});
let ctx = Arc::new(
QueryContextBuilder::default()
.set_extension(TWCS_TIME_WINDOW.to_string(), "1d".to_string())
.build(),
);
let output = GrpcQueryHandler::do_query(instance, request, ctx)
.await
.unwrap();
assert!(matches!(output.data, OutputData::AffectedRows(3)));
let output = execute_sql(&frontend, "show create table auto_created_table").await;
let expected = r#"+--------------------+---------------------------------------------------+
| Table | Create Table |
+--------------------+---------------------------------------------------+
| auto_created_table | CREATE TABLE IF NOT EXISTS "auto_created_table" ( |
| | "a" INT NULL, |
| | "c" JSON NULL, |
| | "ts" TIMESTAMP(3) NOT NULL, |
| | TIME INDEX ("ts") |
| | ) |
| | |
| | ENGINE=mito |
| | WITH( |
| | 'compaction.twcs.time_window' = '1d', |
| | 'compaction.type' = 'twcs' |
| | ) |
+--------------------+---------------------------------------------------+"#;
check_output_stream(output.data, expected).await;
}
}