feat(json2): validate append mode for tables with JSON2 columns (#8434)

* feat: validate append mode for JSON2 tables

* fix: cr by codex

* fix: unit test

* fix: validate JSON2 append_mode for all ALTER TABLE operations
This commit is contained in:
fys
2026-07-08 11:33:36 +08:00
committed by GitHub
parent ebfe4f6eb2
commit 3bf8b9722d
8 changed files with 157 additions and 4 deletions

View File

@@ -84,6 +84,7 @@ use sql::statements::create::{
use sql::statements::statement::Statement;
use sqlparser::ast::{Expr, Ident, UnaryOperator, Value as ParserValue};
use store_api::metric_engine_consts::{LOGICAL_TABLE_METADATA_KEY, METRIC_ENGINE_NAME};
use store_api::mito_engine_options::APPEND_MODE_KEY;
use substrait::{DFLogicalSubstraitConvertor, SubstraitPlan};
use table::TableRef;
use table::dist_table::DistTable;
@@ -2273,13 +2274,15 @@ pub fn verify_alter(
}
}
let _ = table_info
let new_meta = table_info
.meta
.builder_with_alter_kind(table_name, &request.alter_kind)
.context(error::TableSnafu)?
.build()
.context(error::BuildTableMetaSnafu { table_name })?;
validate_json2_columns_append_mode(&new_meta.schema, &new_meta.options)?;
Ok(true)
}
@@ -2328,6 +2331,8 @@ pub fn create_table_info(
let mut table_options = TableOptions::try_from_iter(&create_table.table_options)
.context(UnrecognizedTableOptionSnafu)?;
validate_json2_columns_append_mode(&schema, &table_options)?;
validate_repartition_column_hint(
&mut table_options,
&column_name_to_index_map,
@@ -2370,6 +2375,33 @@ pub fn create_table_info(
Ok(table_info)
}
fn validate_json2_columns_append_mode(schema: &Schema, table_options: &TableOptions) -> Result<()> {
let append_mode = table_options
.extra_options
.get(APPEND_MODE_KEY)
.is_some_and(|value| value == "true");
for column in schema.column_schemas() {
if column
.data_type
.as_json()
.is_some_and(|json_type| json_type.is_json2())
{
ensure!(
append_mode,
InvalidSqlSnafu {
err_msg: format!(
"JSON2 column `{}` requires {}='true'",
column.name, APPEND_MODE_KEY
),
}
);
}
}
Ok(())
}
fn validate_repartition_column_hint(
table_options: &mut TableOptions,
column_name_to_index_map: &HashMap<String, usize>,
@@ -2993,6 +3025,29 @@ WITH ('repartition.column.hint' = ' host ')",
);
}
#[test]
fn test_json2_requires_append_mode() {
let cases = [
"CREATE TABLE monitor (payload JSON2, ts TIMESTAMP TIME INDEX);",
"CREATE TABLE monitor (payload JSON2, ts TIMESTAMP TIME INDEX) WITH (append_mode='false');",
];
for sql in cases {
let expr = create_expr_from_sql(sql);
let err = create_table_info(&expr, vec![]).unwrap_err();
assert!(
err.to_string()
.contains("JSON2 column `payload` requires append_mode='true'"),
"{err}"
);
}
let expr = create_expr_from_sql(
"CREATE TABLE monitor (payload JSON2, ts TIMESTAMP TIME INDEX) WITH (append_mode='true');",
);
create_table_info(&expr, vec![]).unwrap();
}
#[test]
fn test_create_table_with_empty_repartition_column_hint() {
let expr = create_expr_from_sql(

View File

@@ -3003,7 +3003,7 @@ async fn test_create_table_with_json_datatype(instance: Arc<dyn MockInstance>) {
CREATE TABLE b (
j JSON2,
ts TIMESTAMP TIME INDEX,
)"#;
) WITH (append_mode='true')"#;
let output = execute_sql(&instance, sql).await.data;
assert!(matches!(output, OutputData::AffectedRows(0)));
@@ -3019,7 +3019,9 @@ CREATE TABLE b (
| | ) |
| | |
| | ENGINE=mito |
| | |
| | WITH( |
| | append_mode = 'true' |
| | ) |
+-------+----------------------------------+"#;
check_output_stream(output, expected).await;
}

View File

@@ -126,6 +126,8 @@ CREATE TABLE promql_instant_mismatch_nested (
ts TIMESTAMP(3) TIME INDEX,
k STRING PRIMARY KEY,
v JSON2,
) WITH (
'append_mode' = 'true'
);
Affected Rows: 0

View File

@@ -108,6 +108,8 @@ CREATE TABLE promql_instant_mismatch_nested (
ts TIMESTAMP(3) TIME INDEX,
k STRING PRIMARY KEY,
v JSON2,
) WITH (
'append_mode' = 'true'
);
-- TODO(LFC): Uncomment the following SQLs and results when JSON2 is ready.

View File

@@ -230,11 +230,43 @@ drop table json2_table;
Affected Rows: 0
create table json2_without_append_mode (
ts timestamp time index,
j json2
);
Error: 1004(InvalidArguments), Invalid SQL, error: JSON2 column `j` requires append_mode='true'
create table json2_append_mode_false (
ts timestamp time index,
j json2
) with (
'append_mode' = 'false'
);
Error: 1004(InvalidArguments), Invalid SQL, error: JSON2 column `j` requires append_mode='true'
create table json2_alter_non_append (
ts timestamp time index
);
Affected Rows: 0
alter table json2_alter_non_append add column j json2;
Error: 1004(InvalidArguments), Invalid SQL, error: JSON2 column `j` requires append_mode='true'
drop table json2_alter_non_append;
Affected Rows: 0
create table json2_default_null_ok (
ts timestamp time index,
j json2(
a int64 null default null
)
) with (
'append_mode' = 'true'
);
Affected Rows: 0
@@ -252,3 +284,20 @@ create table json2_default_null_check (
Error: 2000(InvalidSyntax), Invalid SQL, error: invalid DEFAULT for JSON2 type hint 'a': Default value should not be null for non null column
create table json2_set_append_mode_false (
ts timestamp time index,
j json2
) with (
'append_mode' = 'true'
);
Affected Rows: 0
alter table json2_set_append_mode_false set 'append_mode' = 'false';
Error: 1004(InvalidArguments), Invalid SQL, error: JSON2 column `j` requires append_mode='true'
drop table json2_set_append_mode_false;
Affected Rows: 0

View File

@@ -71,11 +71,33 @@ select j.d from json2_table order by ts;
drop table json2_table;
create table json2_without_append_mode (
ts timestamp time index,
j json2
);
create table json2_append_mode_false (
ts timestamp time index,
j json2
) with (
'append_mode' = 'false'
);
create table json2_alter_non_append (
ts timestamp time index
);
alter table json2_alter_non_append add column j json2;
drop table json2_alter_non_append;
create table json2_default_null_ok (
ts timestamp time index,
j json2(
a int64 null default null
)
) with (
'append_mode' = 'true'
);
drop table json2_default_null_ok;
@@ -86,3 +108,14 @@ create table json2_default_null_check (
a int64 not null default null
)
);
create table json2_set_append_mode_false (
ts timestamp time index,
j json2
) with (
'append_mode' = 'true'
);
alter table json2_set_append_mode_false set 'append_mode' = 'false';
drop table json2_set_append_mode_false;

View File

@@ -6,6 +6,8 @@ CREATE TABLE json2_type_hints (
user.active BOOLEAN NULL,
score DOUBLE NULL DEFAULT 1.5
)
) WITH (
'append_mode' = 'true'
);
Affected Rows: 0
@@ -27,7 +29,9 @@ SHOW CREATE TABLE json2_type_hints;
| | ) |
| | |
| | ENGINE=mito |
| | |
| | WITH( |
| | append_mode = 'true' |
| | ) |
+------------------+--------------------------------------------------+
INSERT INTO json2_type_hints
@@ -64,6 +68,8 @@ CREATE TABLE json2_type_hints_required (
j JSON2 (
user.age BIGINT NOT NULL
)
) WITH (
'append_mode' = 'true'
);
Affected Rows: 0

View File

@@ -6,6 +6,8 @@ CREATE TABLE json2_type_hints (
user.active BOOLEAN NULL,
score DOUBLE NULL DEFAULT 1.5
)
) WITH (
'append_mode' = 'true'
);
SHOW CREATE TABLE json2_type_hints;
@@ -32,6 +34,8 @@ CREATE TABLE json2_type_hints_required (
j JSON2 (
user.age BIGINT NOT NULL
)
) WITH (
'append_mode' = 'true'
);
INSERT INTO json2_type_hints_required