mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-14 03:50:39 +00:00
feat(operator): allow last_row merge mode with append mode (#8065)
* feat(operator): allow last_row merge_mode when append_mode is enabled - Update RegionOptions::validate to allow last_row merge_mode with append_mode. - Update fill_table_options_for_create to automatically set merge_mode to last_row when append_mode is enabled for LastNonNull table type. - Add unit tests in mito2 and operator to verify options validation and table creation. - Add integration test for InfluxDB write with append mode hint. Signed-off-by: Lei, HUANG <mrsatangel@gmail.com> * fix(operator): simplify append mode options Group `LastNonNull` auto-create options in a single append-mode branch. Files: - `src/operator/src/insert.rs` Signed-off-by: Lei, HUANG <mrsatangel@gmail.com> * fix: sqlness Signed-off-by: Lei, HUANG <mrsatangel@gmail.com> --------- Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
This commit is contained in:
@@ -96,9 +96,10 @@ impl RegionOptions {
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
if self.append_mode {
|
||||
ensure!(
|
||||
self.merge_mode.is_none(),
|
||||
self.merge_mode
|
||||
.is_none_or(|mode| mode == MergeMode::LastRow),
|
||||
InvalidRegionOptionsSnafu {
|
||||
reason: "merge_mode is not allowed when append_mode is enabled",
|
||||
reason: "only last_row merge_mode is allowed when append_mode is enabled",
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -622,6 +623,18 @@ mod tests {
|
||||
assert_eq!(StatusCode::InvalidArguments, err.status_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_append_mode_allows_last_row_merge_mode() {
|
||||
let map = make_map(&[("append_mode", "true"), ("merge_mode", "last_row")]);
|
||||
let options = RegionOptions::try_from(&map).unwrap();
|
||||
assert!(options.append_mode);
|
||||
assert_eq!(MergeMode::LastRow, options.merge_mode());
|
||||
|
||||
let map = make_map(&[("append_mode", "true"), ("merge_mode", "last_non_null")]);
|
||||
let err = RegionOptions::try_from(&map).unwrap_err();
|
||||
assert_eq!(StatusCode::InvalidArguments, err.status_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_all() {
|
||||
let wal_options = WalOptions::Kafka(KafkaWalOptions {
|
||||
|
||||
@@ -1090,7 +1090,15 @@ pub fn fill_table_options_for_create(
|
||||
table_options.insert(APPEND_MODE_KEY.to_string(), "true".to_string());
|
||||
}
|
||||
AutoCreateTableType::LastNonNull => {
|
||||
table_options.insert(MERGE_MODE_KEY.to_string(), "last_non_null".to_string());
|
||||
if ctx
|
||||
.extension(APPEND_MODE_KEY)
|
||||
.is_some_and(|value| value.eq_ignore_ascii_case("true"))
|
||||
{
|
||||
table_options.insert(APPEND_MODE_KEY.to_string(), "true".to_string());
|
||||
table_options.insert(MERGE_MODE_KEY.to_string(), "last_row".to_string());
|
||||
} else {
|
||||
table_options.insert(MERGE_MODE_KEY.to_string(), "last_non_null".to_string());
|
||||
}
|
||||
}
|
||||
AutoCreateTableType::Trace => {
|
||||
table_options.insert(APPEND_MODE_KEY.to_string(), "true".to_string());
|
||||
@@ -1334,4 +1342,56 @@ mod tests {
|
||||
assert_eq!(req_schema[0].column_name, ts_name);
|
||||
assert_eq!(req_schema[1].column_name, field_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_last_non_null_create_options_preserve_default_without_append_mode() {
|
||||
let ctx = Arc::new(QueryContext::with(
|
||||
DEFAULT_CATALOG_NAME,
|
||||
DEFAULT_SCHEMA_NAME,
|
||||
));
|
||||
let mut table_options = Default::default();
|
||||
|
||||
fill_table_options_for_create(&mut table_options, &AutoCreateTableType::LastNonNull, &ctx);
|
||||
|
||||
assert_eq!(
|
||||
Some("last_non_null"),
|
||||
table_options.get(MERGE_MODE_KEY).map(String::as_str)
|
||||
);
|
||||
assert!(!table_options.contains_key(APPEND_MODE_KEY));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_last_non_null_create_options_preserve_default_with_append_mode_false() {
|
||||
let mut ctx = QueryContext::with(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME);
|
||||
ctx.set_extension(APPEND_MODE_KEY, "false");
|
||||
let ctx = Arc::new(ctx);
|
||||
let mut table_options = Default::default();
|
||||
|
||||
fill_table_options_for_create(&mut table_options, &AutoCreateTableType::LastNonNull, &ctx);
|
||||
|
||||
assert!(!table_options.contains_key(APPEND_MODE_KEY));
|
||||
assert_eq!(
|
||||
Some("last_non_null"),
|
||||
table_options.get(MERGE_MODE_KEY).map(String::as_str)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_last_non_null_create_options_use_last_row_with_append_mode_true() {
|
||||
let mut ctx = QueryContext::with(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME);
|
||||
ctx.set_extension(APPEND_MODE_KEY, "true");
|
||||
let ctx = Arc::new(ctx);
|
||||
let mut table_options = Default::default();
|
||||
|
||||
fill_table_options_for_create(&mut table_options, &AutoCreateTableType::LastNonNull, &ctx);
|
||||
|
||||
assert_eq!(
|
||||
Some("true"),
|
||||
table_options.get(APPEND_MODE_KEY).map(String::as_str)
|
||||
);
|
||||
assert_eq!(
|
||||
Some("last_row"),
|
||||
table_options.get(MERGE_MODE_KEY).map(String::as_str)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ macro_rules! http_tests {
|
||||
|
||||
test_influxdb_write,
|
||||
test_influxdb_write_with_hints,
|
||||
test_influxdb_write_with_append_mode_hint,
|
||||
test_http_memory_limit,
|
||||
);
|
||||
)*
|
||||
@@ -3775,6 +3776,42 @@ pub async fn test_influxdb_write_with_hints(storage_type: StorageType) {
|
||||
guard.remove_all().await;
|
||||
}
|
||||
|
||||
pub async fn test_influxdb_write_with_append_mode_hint(storage_type: StorageType) {
|
||||
common_telemetry::init_default_ut_logging();
|
||||
let (app, mut guard) = setup_test_http_app_with_frontend(
|
||||
storage_type,
|
||||
"test_influxdb_write_with_append_mode_hint",
|
||||
)
|
||||
.await;
|
||||
|
||||
let client = TestClient::new(app).await;
|
||||
|
||||
let result = client
|
||||
.post("/v1/influxdb/write?db=public")
|
||||
.header("x-greptime-hint-append_mode", "true")
|
||||
.body("append_mode_table,host=host1 cpu=1.2 1664370459457010101")
|
||||
.send()
|
||||
.await;
|
||||
assert_eq!(result.status(), 204);
|
||||
|
||||
let res = client
|
||||
.get("/v1/sql?sql=show create table append_mode_table")
|
||||
.send()
|
||||
.await;
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
let resp = res.text().await;
|
||||
assert!(
|
||||
resp.contains("append_mode = 'true'"),
|
||||
"expected append_mode = 'true' in SHOW CREATE TABLE output, got: {resp}"
|
||||
);
|
||||
assert!(
|
||||
resp.contains("merge_mode = 'last_row'"),
|
||||
"expected merge_mode = 'last_row' in SHOW CREATE TABLE output, got: {resp}"
|
||||
);
|
||||
|
||||
guard.remove_all().await;
|
||||
}
|
||||
|
||||
/// Test one-to-many VRL pipeline expansion.
|
||||
/// This test verifies that a VRL processor can return an array, which results in
|
||||
/// multiple output rows from a single input row.
|
||||
|
||||
@@ -181,5 +181,5 @@ create table if not exists invalid_merge_mode(
|
||||
engine=mito
|
||||
with('merge_mode'='last_non_null', 'append_mode'='true');
|
||||
|
||||
Error: 1004(InvalidArguments), Invalid region options, merge_mode is not allowed when append_mode is enabled
|
||||
Error: 1004(InvalidArguments), Invalid region options, only last_row merge_mode is allowed when append_mode is enabled
|
||||
|
||||
|
||||
Reference in New Issue
Block a user