mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-04 19:15:34 +00:00
feat(json2): support altering JSON2 settings (#9029)
* feat(sql): support alter syntax for JSON2 columns Signed-off-by: fys <fengys1996@gmail.com> * fix(json2): preserve rows on type hint mismatch during compaction * refactor(json2): simplify alter settings handling * fix(json2): preserve coerced values during compaction * chore: remove unnecessary clone * chor: reduce memory allocations * fix: cargo clippy * chore: update greptime-proto to main branch * refactor(datatypes): unify string handling with other JSON type hints * fix: cr --------- Signed-off-by: fys <fengys1996@gmail.com>
This commit is contained in:
@@ -462,19 +462,19 @@ impl ParserContext<'_> {
|
||||
.context(error::SyntaxSnafu)?;
|
||||
self.parse_alter_table_drop_default(column_name)
|
||||
} else {
|
||||
let (data_type, json2_options) =
|
||||
if let Some(json2) = parse_json2_type_and_options(&mut self.parser)? {
|
||||
json2
|
||||
} else {
|
||||
(
|
||||
self.parser.parse_data_type().context(error::SyntaxSnafu)?,
|
||||
None,
|
||||
)
|
||||
};
|
||||
if let Some((_, json2_options)) =
|
||||
parse_json2_type_and_options(&mut self.parser)?
|
||||
{
|
||||
return Ok(AlterTableOperation::SetJsonSettings {
|
||||
column_name,
|
||||
json2_options,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(AlterTableOperation::ModifyColumnType {
|
||||
column_name,
|
||||
target_type: data_type,
|
||||
json2_options,
|
||||
target_type: self.parser.parse_data_type().context(error::SyntaxSnafu)?,
|
||||
json2_options: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1576,9 +1576,8 @@ MODIFY COLUMN attrs JSON2 (
|
||||
let Statement::AlterTable(alter_table) = statements.remove(0) else {
|
||||
unreachable!()
|
||||
};
|
||||
let AlterTableOperation::ModifyColumnType {
|
||||
let AlterTableOperation::SetJsonSettings {
|
||||
column_name,
|
||||
target_type,
|
||||
json2_options: Some(options),
|
||||
} = alter_table.alter_operation()
|
||||
else {
|
||||
@@ -1586,7 +1585,6 @@ MODIFY COLUMN attrs JSON2 (
|
||||
};
|
||||
|
||||
assert_eq!("attrs", column_name.value);
|
||||
assert_eq!("JSON2", target_type.to_string());
|
||||
assert_eq!(Some(2000), options.max_auto_expanded_paths);
|
||||
assert_eq!(4, options.type_hints.len());
|
||||
assert_eq!(vec!["user", "id"], options.type_hints[1].path);
|
||||
@@ -1610,7 +1608,7 @@ MODIFY COLUMN attrs JSON2 (
|
||||
let Statement::AlterTable(empty) = empty.remove(0) else {
|
||||
unreachable!()
|
||||
};
|
||||
let AlterTableOperation::ModifyColumnType { json2_options, .. } = empty.alter_operation()
|
||||
let AlterTableOperation::SetJsonSettings { json2_options, .. } = empty.alter_operation()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
@@ -88,6 +88,11 @@ pub enum AlterTableOperation {
|
||||
target_type: DataType,
|
||||
json2_options: Option<Json2Options>,
|
||||
},
|
||||
/// `MODIFY <column_name> JSON2 [json2_options]`
|
||||
SetJsonSettings {
|
||||
column_name: Ident,
|
||||
json2_options: Option<Json2Options>,
|
||||
},
|
||||
/// `SET <table attrs key> = <table attr value>`
|
||||
SetTableOptions {
|
||||
options: Vec<KeyValueOption>,
|
||||
@@ -265,6 +270,16 @@ impl Display for AlterTableOperation {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AlterTableOperation::SetJsonSettings {
|
||||
column_name,
|
||||
json2_options,
|
||||
} => {
|
||||
write!(f, r#"MODIFY COLUMN {column_name} JSON2"#)?;
|
||||
if let Some(options) = json2_options {
|
||||
write!(f, "{options}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AlterTableOperation::SetTableOptions { options } => {
|
||||
let kvs = options
|
||||
.iter()
|
||||
@@ -433,8 +448,10 @@ impl Display for AlterDatabaseOperation {
|
||||
mod tests {
|
||||
use std::assert_matches;
|
||||
|
||||
use super::AlterTableOperation;
|
||||
use crate::dialect::GreptimeDbDialect;
|
||||
use crate::parser::{ParseOptions, ParserContext};
|
||||
use crate::statements::create::Json2Options;
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
#[test]
|
||||
@@ -503,7 +520,7 @@ ALTER TABLE monitor ADD COLUMN app STRING DEFAULT 'shop' PRIMARY KEY, ADD COLUMN
|
||||
}
|
||||
|
||||
let sql = r"alter table monitor modify column load_15 string;";
|
||||
let stmts =
|
||||
let mut stmts =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
.unwrap();
|
||||
assert_eq!(1, stmts.len());
|
||||
@@ -523,6 +540,25 @@ ALTER TABLE monitor MODIFY COLUMN load_15 STRING"#,
|
||||
}
|
||||
}
|
||||
|
||||
let Statement::AlterTable(alter_table) = &mut stmts[0] else {
|
||||
unreachable!();
|
||||
};
|
||||
let AlterTableOperation::ModifyColumnType { json2_options, .. } =
|
||||
alter_table.alter_operation_mut()
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
*json2_options = Some(Json2Options {
|
||||
max_auto_expanded_paths: Some(1),
|
||||
type_hints: vec![],
|
||||
});
|
||||
assert_eq!(
|
||||
r#"ALTER TABLE monitor MODIFY COLUMN load_15 STRING(
|
||||
max_auto_expanded_paths = 1
|
||||
)"#,
|
||||
alter_table.to_string()
|
||||
);
|
||||
|
||||
let sql = r"alter table monitor drop column load_15;";
|
||||
let stmts =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
|
||||
@@ -157,6 +157,26 @@ impl Display for Json2Options {
|
||||
}
|
||||
}
|
||||
|
||||
impl Json2Options {
|
||||
pub fn build_json_settings(&self) -> Result<JsonSettings> {
|
||||
let type_hints = self
|
||||
.type_hints
|
||||
.iter()
|
||||
.map(|hint| {
|
||||
Ok(datatypes::json::JsonTypeHint {
|
||||
path: hint.path.clone(),
|
||||
data_type: json_type_hint_concrete_data_type(&hint.data_type)?,
|
||||
inverted_index: hint.inverted_index,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let max_auto_expanded_paths = self
|
||||
.max_auto_expanded_paths
|
||||
.or(Some(JSON2_DEFAULT_MAX_AUTO_EXPANDED_PATHS));
|
||||
JsonSettings::try_new(type_hints, max_auto_expanded_paths).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct JsonTypeHint {
|
||||
pub path: Vec<String>,
|
||||
@@ -351,24 +371,7 @@ impl ColumnExtensions {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let type_hints = options
|
||||
.type_hints
|
||||
.iter()
|
||||
.map(|hint| {
|
||||
Ok(datatypes::json::JsonTypeHint {
|
||||
path: hint.path.clone(),
|
||||
data_type: json_type_hint_concrete_data_type(&hint.data_type)?,
|
||||
inverted_index: hint.inverted_index,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let settings = JsonSettings::try_new(
|
||||
type_hints,
|
||||
options
|
||||
.max_auto_expanded_paths
|
||||
.or(Some(JSON2_DEFAULT_MAX_AUTO_EXPANDED_PATHS)),
|
||||
)?;
|
||||
Ok(Some(settings))
|
||||
options.build_json_settings().map(Some)
|
||||
}
|
||||
|
||||
pub fn set_json_settings(&mut self, settings: JsonSettings) -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user