diff --git a/src/datatypes/src/json.rs b/src/datatypes/src/json.rs index cd73e202bf3..e3c408698eb 100644 --- a/src/datatypes/src/json.rs +++ b/src/datatypes/src/json.rs @@ -237,19 +237,10 @@ fn validate_type_hints(type_hints: &[JsonTypeHint]) -> Result<()> { } let data_type = match &hint.data_type { ConcreteDataType::Boolean(_) - | ConcreteDataType::UInt8(_) - | ConcreteDataType::UInt16(_) - | ConcreteDataType::UInt32(_) | ConcreteDataType::UInt64(_) - | ConcreteDataType::Int8(_) - | ConcreteDataType::Int16(_) - | ConcreteDataType::Int32(_) | ConcreteDataType::Int64(_) - | ConcreteDataType::Float32(_) | ConcreteDataType::Float64(_) - | ConcreteDataType::String(_) - | ConcreteDataType::List(_) - | ConcreteDataType::Struct(_) => (&hint.data_type).into(), + | ConcreteDataType::String(_) => (&hint.data_type).into(), data_type => { return InvalidJson2SettingsSnafu { reason: format!("unsupported JSON2 type hint data type: {data_type}"), diff --git a/src/sql/src/parsers/create_parser/json.rs b/src/sql/src/parsers/create_parser/json.rs index 2bf3c9407a6..0adadc1d193 100644 --- a/src/sql/src/parsers/create_parser/json.rs +++ b/src/sql/src/parsers/create_parser/json.rs @@ -25,7 +25,6 @@ use crate::dialect::GreptimeDbDialect; use crate::error::{InvalidSqlSnafu, Result, SyntaxSnafu}; use crate::parsers::create_parser::{INVERTED, SKIPPING}; use crate::statements::create::{Json2Options, JsonTypeHint}; -use crate::statements::transform::type_alias::get_type_by_alias; const JSON2_TYPE_NAME: &str = "JSON2"; const MAX_AUTO_EXPANDED_PATHS: &str = "max_auto_expanded_paths"; @@ -155,7 +154,7 @@ fn parse_json2_type_hint(parser: &mut Parser<'_>) -> Result { } ); let data_type = parser.parse_data_type().context(SyntaxSnafu)?; - let data_type = normalize_json2_type_hint_type(data_type)?; + let data_type = validate_json2_type_hint_type(data_type)?; let mut inverted_index = false; @@ -238,35 +237,23 @@ fn parse_json2_path(parser: &mut Parser<'_>) -> Result> { Ok(path) } -fn normalize_json2_type_hint_type(data_type: DataType) -> Result { - let data_type = get_type_by_alias(&data_type).unwrap_or(data_type); - let normalized = match data_type { - DataType::String(_) | DataType::Text | DataType::Varchar(_) | DataType::Char(_) => { - DataType::String(None) +fn validate_json2_type_hint_type(data_type: DataType) -> Result { + match data_type { + DataType::Int64 + | DataType::UInt64 + | DataType::Float64 + | DataType::String(None) + | DataType::BigInt(None) + | DataType::BigIntUnsigned(None) + | DataType::Double(ExactNumberInfo::None) + | DataType::Boolean => Ok(data_type), + _ => InvalidSqlSnafu { + msg: format!( + "unsupported JSON2 type hint data type: {data_type}; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64" + ), } - DataType::TinyInt(_) - | DataType::SmallInt(_) - | DataType::Int(_) - | DataType::Integer(_) - | DataType::BigInt(_) => DataType::BigInt(None), - DataType::TinyIntUnsigned(_) - | DataType::SmallIntUnsigned(_) - | DataType::IntUnsigned(_) - | DataType::UnsignedInteger - | DataType::BigIntUnsigned(_) => DataType::BigIntUnsigned(None), - DataType::Float(_) | DataType::Real | DataType::Double(_) => { - DataType::Double(ExactNumberInfo::None) - } - DataType::Boolean => DataType::Boolean, - _ => { - return InvalidSqlSnafu { - msg: format!("unsupported JSON2 type hint data type: {data_type}"), - } - .fail(); - } - }; - - Ok(normalized) + .fail(), + } } fn ensure_no_path_conflict(hints: &[JsonTypeHint], path: &[String]) -> Result<()> { @@ -330,7 +317,7 @@ CREATE TABLE traces ( log_json_data JSON2 ( "service.name" STRING INVERTED INDEX, http.method STRING, - status_code INT64, + status_code BIGINT, comment STRING, ), ts TIMESTAMP TIME INDEX, @@ -463,40 +450,81 @@ CREATE TABLE traces ( } #[test] - fn test_parse_json2_type_hint_normalizes_numeric_types() { - let column = parse_json2_column( - r#" -CREATE TABLE traces ( - log_json_data JSON2 ( - tinyint_value TINYINT, - smallint_value SMALLINT, - int_value INT, - integer_value INTEGER, - bigint_value BIGINT, - int64_value INT64, - tinyuint_value TINYINT UNSIGNED, - smalluint_value SMALLINT UNSIGNED, - uint_value INT UNSIGNED, - uint64_value UINT64, - float_value FLOAT, - real_value REAL, - double_value DOUBLE, - float64_value FLOAT64 - ), - ts TIMESTAMP TIME INDEX, -)"#, - ); + fn test_parse_json2_type_hint_supported_types() { + for (sql_type, expected) in [ + ("STRING", DataType::String(None)), + ("BIGINT", DataType::BigInt(None)), + ("BIGINT UNSIGNED", DataType::BigIntUnsigned(None)), + ("DOUBLE", DataType::Double(ExactNumberInfo::None)), + ("BOOLEAN", DataType::Boolean), + ("INT64", DataType::Int64), + ("UINT64", DataType::UInt64), + ("FLOAT64", DataType::Float64), + ] { + for sql_type in [sql_type.to_string(), sql_type.to_lowercase()] { + let column = parse_json2_column(&format!( + "CREATE TABLE traces (j JSON2 (value {sql_type}), ts TIMESTAMP TIME INDEX)" + )); + let options = column.extensions.json2_options.unwrap(); + let settings = options.build_json_settings().unwrap(); + assert_eq!(settings.type_hints().len(), 1); + let hints = options.type_hints; + assert_eq!(hints[0].data_type, expected); + } + } + } - let hints = column.extensions.json2_options.unwrap().type_hints; - assert_eq!(hints.len(), 14); - for hint in hints.iter().take(6) { - assert_eq!(hint.data_type, DataType::BigInt(None)); - } - for hint in hints.iter().skip(6).take(4) { - assert_eq!(hint.data_type, DataType::BigIntUnsigned(None)); - } - for hint in hints.iter().skip(10) { - assert_eq!(hint.data_type, DataType::Double(ExactNumberInfo::None)); + #[test] + fn test_parse_json2_type_hint_rejects_unsupported_types() { + for sql_type in [ + "INT2", + "INT4", + "INT8", + "INT16", + "INT32", + "TINYINT", + "SMALLINT", + "INT", + "INTEGER", + "UINT8", + "UINT16", + "UINT32", + "TINYINT UNSIGNED", + "SMALLINT UNSIGNED", + "INT UNSIGNED", + "FLOAT", + "REAL", + "FLOAT4", + "FLOAT8", + "FLOAT32", + "BOOL", + "TEXT", + "VARCHAR(10)", + "CHAR(10)", + "TIMESTAMP", + "DECIMAL(10, 2)", + "STRING(10)", + "BIGINT(10)", + ] { + for sql in [ + format!( + "CREATE TABLE traces (j JSON2 (value {sql_type}), ts TIMESTAMP TIME INDEX)" + ), + format!("ALTER TABLE traces MODIFY COLUMN j JSON2 (value {sql_type})"), + ] { + let err = ParserContext::create_with_dialect( + &sql, + &GreptimeDbDialect {}, + ParseOptions::default(), + ) + .unwrap_err(); + assert!( + err.to_string().contains( + "supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64" + ), + "{sql}: {err}" + ); + } } } @@ -504,7 +532,7 @@ CREATE TABLE traces ( fn test_parse_json2_type_hint_rejects_default() { for default in ["-5", "abs(-1)"] { let sql = format!( - "CREATE TABLE traces (log_json_data JSON2 (status_code INT64 DEFAULT {default}), ts TIMESTAMP TIME INDEX)" + "CREATE TABLE traces (log_json_data JSON2 (status_code BIGINT DEFAULT {default}), ts TIMESTAMP TIME INDEX)" ); let err = ParserContext::create_with_dialect( &sql, @@ -521,7 +549,7 @@ CREATE TABLE traces ( let result = ParserContext::create_with_dialect( r#" CREATE TABLE traces ( - log_json_data JSON2 (a.b STRING, a.b INT64), + log_json_data JSON2 (a.b STRING, a.b BIGINT), ts TIMESTAMP TIME INDEX, )"#, &GreptimeDbDialect {}, @@ -537,7 +565,7 @@ CREATE TABLE traces ( let result = ParserContext::create_with_dialect( r#" CREATE TABLE traces ( - log_json_data JSON2 (a STRING, a.b INT64), + log_json_data JSON2 (a STRING, a.b BIGINT), ts TIMESTAMP TIME INDEX, )"#, &GreptimeDbDialect {}, diff --git a/src/sql/src/statements.rs b/src/sql/src/statements.rs index 808e30f842c..e3f684bfcc2 100644 --- a/src/sql/src/statements.rs +++ b/src/sql/src/statements.rs @@ -225,7 +225,9 @@ pub fn sql_column_def_to_grpc_column_def( pub fn sql_data_type_to_concrete_data_type(data_type: &SqlDataType) -> Result { match data_type { SqlDataType::BigInt(_) | SqlDataType::Int64 => Ok(ConcreteDataType::int64_datatype()), - SqlDataType::BigIntUnsigned(_) => Ok(ConcreteDataType::uint64_datatype()), + SqlDataType::BigIntUnsigned(_) | SqlDataType::UInt64 => { + Ok(ConcreteDataType::uint64_datatype()) + } SqlDataType::Int(_) | SqlDataType::Integer(_) => Ok(ConcreteDataType::int32_datatype()), SqlDataType::IntUnsigned(_) | SqlDataType::UnsignedInteger => { Ok(ConcreteDataType::uint32_datatype()) @@ -422,6 +424,7 @@ mod tests { SqlDataType::BigIntUnsigned(None), ConcreteDataType::uint64_datatype(), ); + check_type(SqlDataType::UInt64, ConcreteDataType::uint64_datatype()); check_type( SqlDataType::IntUnsigned(None), ConcreteDataType::uint32_datatype(), diff --git a/src/sql/src/statements/create.rs b/src/sql/src/statements/create.rs index 2310531841c..7c31790deaf 100644 --- a/src/sql/src/statements/create.rs +++ b/src/sql/src/statements/create.rs @@ -165,7 +165,7 @@ impl Json2Options { .map(|hint| { Ok(datatypes::json::JsonTypeHint { path: hint.path.clone(), - data_type: json_type_hint_concrete_data_type(&hint.data_type)?, + data_type: sql_data_type_to_concrete_data_type(&hint.data_type)?, inverted_index: hint.inverted_index, }) }) @@ -396,47 +396,19 @@ impl ColumnExtensions { } } -fn json_type_hint_concrete_data_type(data_type: &DataType) -> Result { - let data_type = sql_data_type_to_concrete_data_type(data_type)?; - normalize_json_type_hint_concrete_data_type(&data_type) -} - -fn normalize_json_type_hint_concrete_data_type( - data_type: &ConcreteDataType, -) -> Result { - let normalized = match data_type { - ConcreteDataType::String(_) => ConcreteDataType::string_datatype(), - ConcreteDataType::Int8(_) - | ConcreteDataType::Int16(_) - | ConcreteDataType::Int32(_) - | ConcreteDataType::Int64(_) => ConcreteDataType::int64_datatype(), - ConcreteDataType::UInt8(_) - | ConcreteDataType::UInt16(_) - | ConcreteDataType::UInt32(_) - | ConcreteDataType::UInt64(_) => ConcreteDataType::uint64_datatype(), - ConcreteDataType::Float32(_) | ConcreteDataType::Float64(_) => { - ConcreteDataType::float64_datatype() - } - ConcreteDataType::Boolean(_) => ConcreteDataType::boolean_datatype(), - _ => { - return InvalidSqlSnafu { - msg: format!("unsupported JSON2 type hint data type: {data_type}"), - } - .fail(); - } - }; - Ok(normalized) -} - fn json_type_hint_sql_data_type(data_type: &ConcreteDataType) -> Result { - let data_type = normalize_json_type_hint_concrete_data_type(data_type)?; let sql_type = match data_type { ConcreteDataType::String(_) => DataType::String(None), ConcreteDataType::Int64(_) => DataType::BigInt(None), ConcreteDataType::UInt64(_) => DataType::BigIntUnsigned(None), ConcreteDataType::Float64(_) => DataType::Double(sqlparser::ast::ExactNumberInfo::None), ConcreteDataType::Boolean(_) => DataType::Boolean, - _ => unreachable!("JSON2 type hint data type should have been normalized"), + _ => { + return InvalidSqlSnafu { + msg: format!("unsupported JSON2 type hint data type: {data_type}"), + } + .fail(); + } }; Ok(sql_type) } @@ -933,7 +905,7 @@ ENGINE=mito let sql = r#"CREATE TABLE traces ( log_json_data JSON2 ( "service.name" STRING, - "a.b"."c" INT64, + "a.b"."c" BIGINT, a."b.c" STRING ), ts TIMESTAMP TIME INDEX @@ -977,7 +949,7 @@ ENGINE=mito fn test_parse_json2_max_auto_expanded_paths_option() -> Result<()> { let sql = r#"CREATE TABLE traces ( log_json_data JSON2 ( - status_code INT64, + status_code BIGINT, max_auto_expanded_paths = 1 ), ts TIMESTAMP TIME INDEX @@ -1003,7 +975,7 @@ ENGINE=mito let sql = r#"CREATE TABLE traces ( log_json_data JSON2 ( "1abc" STRING, - a."2b" INT64 + a."2b" BIGINT ), ts TIMESTAMP TIME INDEX )"#; @@ -1045,8 +1017,8 @@ ENGINE=mito fn test_json2_type_hint_rejects_default() { let sql = r#"CREATE TABLE traces ( log_json_data JSON2 ( - status_code INT64 DEFAULT -5, - duration FLOAT64 DEFAULT +1.5, + status_code BIGINT DEFAULT -5, + duration DOUBLE DEFAULT +1.5, error BOOLEAN DEFAULT false, message STRING DEFAULT 'unknown' ), @@ -1062,7 +1034,7 @@ ENGINE=mito fn test_json2_type_hint_rejects_not_null() { let sql = r#"CREATE TABLE traces ( log_json_data JSON2 ( - status_code INT64 NOT NULL DEFAULT NULL + status_code BIGINT NOT NULL DEFAULT NULL ), ts TIMESTAMP TIME INDEX )"#; @@ -1073,23 +1045,23 @@ ENGINE=mito } #[test] - fn test_set_json_settings_normalizes_type_hint_sql_types() -> Result<()> { + fn test_set_json_settings_preserves_type_hint_sql_types() -> Result<()> { let mut extensions = super::ColumnExtensions::default(); let settings = JsonSettings::try_new( vec![ DatatypeJsonTypeHint { path: vec!["i".to_string()], - data_type: ConcreteDataType::int32_datatype(), + data_type: ConcreteDataType::int64_datatype(), inverted_index: false, }, DatatypeJsonTypeHint { path: vec!["f".to_string()], - data_type: ConcreteDataType::float32_datatype(), + data_type: ConcreteDataType::float64_datatype(), inverted_index: false, }, DatatypeJsonTypeHint { path: vec!["u".to_string()], - data_type: ConcreteDataType::uint32_datatype(), + data_type: ConcreteDataType::uint64_datatype(), inverted_index: false, }, DatatypeJsonTypeHint { diff --git a/tests/cases/standalone/common/types/json/json2_alter.result b/tests/cases/standalone/common/types/json/json2_alter.result index ab9e39dc777..153aa9e7902 100644 --- a/tests/cases/standalone/common/types/json/json2_alter.result +++ b/tests/cases/standalone/common/types/json/json2_alter.result @@ -18,7 +18,7 @@ ALTER TABLE application_logs MODIFY COLUMN attrs JSON2 ( max_auto_expanded_paths = 2000, service STRING, - duration INT64, + duration BIGINT, trace_id STRING ); diff --git a/tests/cases/standalone/common/types/json/json2_alter.sql b/tests/cases/standalone/common/types/json/json2_alter.sql index 7fce02b76ee..457943e93f6 100644 --- a/tests/cases/standalone/common/types/json/json2_alter.sql +++ b/tests/cases/standalone/common/types/json/json2_alter.sql @@ -14,7 +14,7 @@ ALTER TABLE application_logs MODIFY COLUMN attrs JSON2 ( max_auto_expanded_paths = 2000, service STRING, - duration INT64, + duration BIGINT, trace_id STRING ); diff --git a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.result b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.result index 284b7e6f850..aaefd5ff0ca 100644 --- a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.result +++ b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.result @@ -24,7 +24,7 @@ ADMIN FLUSH_TABLE('json2_alter_type_hints_compaction'); ALTER TABLE json2_alter_type_hints_compaction MODIFY COLUMN attrs JSON2 ( - kind INT64 + kind BIGINT ); Affected Rows: 0 diff --git a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.sql b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.sql index 45d859d4ece..34a16dafbb7 100644 --- a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.sql +++ b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction.sql @@ -14,7 +14,7 @@ ADMIN FLUSH_TABLE('json2_alter_type_hints_compaction'); ALTER TABLE json2_alter_type_hints_compaction MODIFY COLUMN attrs JSON2 ( - kind INT64 + kind BIGINT ); INSERT INTO json2_alter_type_hints_compaction VALUES diff --git a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.result b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.result index 5ba2cf4700a..e3517c90e38 100644 --- a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.result +++ b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.result @@ -24,7 +24,7 @@ ADMIN FLUSH_TABLE('json2_alter_type_hints_compaction_conversion'); ALTER TABLE json2_alter_type_hints_compaction_conversion MODIFY COLUMN attrs JSON2 ( to_string STRING, - to_int INT64 + to_int BIGINT ); Affected Rows: 0 diff --git a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.sql b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.sql index de9f211cfb5..cfadce89a93 100644 --- a/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.sql +++ b/tests/cases/standalone/common/types/json/json2_alter_type_hints_compaction_conversion.sql @@ -14,7 +14,7 @@ ADMIN FLUSH_TABLE('json2_alter_type_hints_compaction_conversion'); ALTER TABLE json2_alter_type_hints_compaction_conversion MODIFY COLUMN attrs JSON2 ( to_string STRING, - to_int INT64 + to_int BIGINT ); INSERT INTO json2_alter_type_hints_compaction_conversion VALUES diff --git a/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.result b/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.result index 6e0f833ccd6..5ad7a46ce83 100644 --- a/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.result +++ b/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.result @@ -24,7 +24,7 @@ ADMIN FLUSH_TABLE('json2_compaction_null_type_hint_mismatch'); ALTER TABLE json2_compaction_null_type_hint_mismatch MODIFY COLUMN attrs JSON2 ( - kind INT64 + kind BIGINT ); Affected Rows: 0 diff --git a/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.sql b/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.sql index 7ebff9cceb1..8025977c380 100644 --- a/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.sql +++ b/tests/cases/standalone/common/types/json/json2_compaction_null_type_hint_mismatch.sql @@ -14,7 +14,7 @@ ADMIN FLUSH_TABLE('json2_compaction_null_type_hint_mismatch'); ALTER TABLE json2_compaction_null_type_hint_mismatch MODIFY COLUMN attrs JSON2 ( - kind INT64 + kind BIGINT ); INSERT INTO json2_compaction_null_type_hint_mismatch VALUES diff --git a/tests/cases/standalone/common/types/json/json2_type_hints.result b/tests/cases/standalone/common/types/json/json2_type_hints.result index 1a892b6e4cb..eda5aee7692 100644 --- a/tests/cases/standalone/common/types/json/json2_type_hints.result +++ b/tests/cases/standalone/common/types/json/json2_type_hints.result @@ -71,7 +71,7 @@ CREATE TABLE json2_type_hints_timestamp ( ) ); -Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: TIMESTAMP +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: TIMESTAMP; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 -- A type hint at the maximum supported depth is accepted. CREATE TABLE json2_type_hint_depth_50 ( @@ -105,3 +105,132 @@ DROP TABLE json2_type_hint_depth_50; Affected Rows: 0 +-- Type hints reject unsupported types and aliases. +CREATE TABLE json2_hint_int8 (ts TIMESTAMP TIME INDEX, j JSON2 (value INT8)); + +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: INT8; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 + +CREATE TABLE json2_hint_tinyint (ts TIMESTAMP TIME INDEX, j JSON2 (value TINYINT)); + +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: TINYINT; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 + +CREATE TABLE json2_hint_uint8 (ts TIMESTAMP TIME INDEX, j JSON2 (value UINT8)); + +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: UInt8; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 + +CREATE TABLE json2_hint_float (ts TIMESTAMP TIME INDEX, j JSON2 (value FLOAT)); + +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: FLOAT; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 + +CREATE TABLE json2_hint_text (ts TIMESTAMP TIME INDEX, j JSON2 (value TEXT)); + +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: TEXT; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 + +CREATE TABLE json2_hint_unsigned ( + ts TIMESTAMP TIME INDEX, + j JSON2 (value BIGINT UNSIGNED) +) WITH ('append_mode' = 'true'); + +Affected Rows: 0 + +INSERT INTO json2_hint_unsigned VALUES (1, '{"value":18446744073709551615}'); + +Affected Rows: 1 + +SELECT j.value FROM json2_hint_unsigned; + ++--------------------------------------------------------------+ +| json_get(json2_hint_unsigned.j,Utf8("$.value"),UInt64(NULL)) | ++--------------------------------------------------------------+ +| 18446744073709551615 | ++--------------------------------------------------------------+ + +ALTER TABLE json2_hint_unsigned MODIFY COLUMN j JSON2 (value INT8); + +Error: 2000(InvalidSyntax), Invalid SQL, error: unsupported JSON2 type hint data type: INT8; supported types: STRING, BIGINT, BIGINT UNSIGNED, DOUBLE, BOOLEAN; supported aliases: INT64, UINT64, FLOAT64 + +DROP TABLE json2_hint_unsigned; + +Affected Rows: 0 + +-- These aliases preserve the exact type and are displayed using canonical names. +CREATE TABLE json2_hint_aliases ( + ts TIMESTAMP TIME INDEX, + j JSON2 (i INT64, u UINT64, f FLOAT64) +) WITH ('append_mode' = 'true'); + +Affected Rows: 0 + +SHOW CREATE TABLE json2_hint_aliases; + ++--------------------+---------------------------------------------------+ +| Table | Create Table | ++--------------------+---------------------------------------------------+ +| json2_hint_aliases | CREATE TABLE IF NOT EXISTS "json2_hint_aliases" ( | +| | "ts" TIMESTAMP(3) NOT NULL, | +| | "j" JSON2( | +| | max_auto_expanded_paths = 100, | +| | "i" BIGINT, | +| | "u" BIGINT UNSIGNED, | +| | "f" DOUBLE | +| | ) NULL, | +| | TIME INDEX ("ts") | +| | ) | +| | | +| | ENGINE=mito | +| | WITH( | +| | append_mode = 'true' | +| | ) | ++--------------------+---------------------------------------------------+ + +INSERT INTO json2_hint_aliases VALUES + (1, '{"i":-9223372036854775808,"u":18446744073709551615,"f":1.5}'); + +Affected Rows: 1 + +SELECT j.i AS i, j.u AS u, j.f AS f FROM json2_hint_aliases; + ++----------------------+----------------------+-----+ +| i | u | f | ++----------------------+----------------------+-----+ +| -9223372036854775808 | 18446744073709551615 | 1.5 | ++----------------------+----------------------+-----+ + +ALTER TABLE json2_hint_aliases MODIFY COLUMN j JSON2 (i INT64, u UINT64, f FLOAT64); + +Affected Rows: 0 + +SHOW CREATE TABLE json2_hint_aliases; + ++--------------------+---------------------------------------------------+ +| Table | Create Table | ++--------------------+---------------------------------------------------+ +| json2_hint_aliases | CREATE TABLE IF NOT EXISTS "json2_hint_aliases" ( | +| | "ts" TIMESTAMP(3) NOT NULL, | +| | "j" JSON2( | +| | max_auto_expanded_paths = 100, | +| | "i" BIGINT, | +| | "u" BIGINT UNSIGNED, | +| | "f" DOUBLE | +| | ) NULL, | +| | TIME INDEX ("ts") | +| | ) | +| | | +| | ENGINE=mito | +| | WITH( | +| | append_mode = 'true' | +| | ) | ++--------------------+---------------------------------------------------+ + +SELECT j.i AS i, j.u AS u, j.f AS f FROM json2_hint_aliases; + ++----------------------+----------------------+-----+ +| i | u | f | ++----------------------+----------------------+-----+ +| -9223372036854775808 | 18446744073709551615 | 1.5 | ++----------------------+----------------------+-----+ + +DROP TABLE json2_hint_aliases; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/types/json/json2_type_hints.sql b/tests/cases/standalone/common/types/json/json2_type_hints.sql index aa88ae60bf0..3b301700333 100644 --- a/tests/cases/standalone/common/types/json/json2_type_hints.sql +++ b/tests/cases/standalone/common/types/json/json2_type_hints.sql @@ -59,3 +59,48 @@ CREATE TABLE json2_type_hint_depth_51 ( DROP TABLE json2_type_hints; DROP TABLE json2_type_hint_depth_50; + +-- Type hints reject unsupported types and aliases. +CREATE TABLE json2_hint_int8 (ts TIMESTAMP TIME INDEX, j JSON2 (value INT8)); + +CREATE TABLE json2_hint_tinyint (ts TIMESTAMP TIME INDEX, j JSON2 (value TINYINT)); + +CREATE TABLE json2_hint_uint8 (ts TIMESTAMP TIME INDEX, j JSON2 (value UINT8)); + +CREATE TABLE json2_hint_float (ts TIMESTAMP TIME INDEX, j JSON2 (value FLOAT)); + +CREATE TABLE json2_hint_text (ts TIMESTAMP TIME INDEX, j JSON2 (value TEXT)); + +CREATE TABLE json2_hint_unsigned ( + ts TIMESTAMP TIME INDEX, + j JSON2 (value BIGINT UNSIGNED) +) WITH ('append_mode' = 'true'); + +INSERT INTO json2_hint_unsigned VALUES (1, '{"value":18446744073709551615}'); + +SELECT j.value FROM json2_hint_unsigned; + +ALTER TABLE json2_hint_unsigned MODIFY COLUMN j JSON2 (value INT8); + +DROP TABLE json2_hint_unsigned; + +-- These aliases preserve the exact type and are displayed using canonical names. +CREATE TABLE json2_hint_aliases ( + ts TIMESTAMP TIME INDEX, + j JSON2 (i INT64, u UINT64, f FLOAT64) +) WITH ('append_mode' = 'true'); + +SHOW CREATE TABLE json2_hint_aliases; + +INSERT INTO json2_hint_aliases VALUES + (1, '{"i":-9223372036854775808,"u":18446744073709551615,"f":1.5}'); + +SELECT j.i AS i, j.u AS u, j.f AS f FROM json2_hint_aliases; + +ALTER TABLE json2_hint_aliases MODIFY COLUMN j JSON2 (i INT64, u UINT64, f FLOAT64); + +SHOW CREATE TABLE json2_hint_aliases; + +SELECT j.i AS i, j.u AS u, j.f AS f FROM json2_hint_aliases; + +DROP TABLE json2_hint_aliases;