diff --git a/be/src/vec/data_types/serde/data_type_object_serde.cpp b/be/src/vec/data_types/serde/data_type_object_serde.cpp index fc536d9ef0df7b..c450ee60e27fec 100644 --- a/be/src/vec/data_types/serde/data_type_object_serde.cpp +++ b/be/src/vec/data_types/serde/data_type_object_serde.cpp @@ -87,6 +87,12 @@ Status DataTypeObjectSerDe::write_column_to_mysql(const IColumn& column, return _write_column_to_mysql(column, row_buffer, row_idx, col_const, options); } +Status DataTypeObjectSerDe::serialize_column_to_json(const IColumn& column, int64_t start_idx, + int64_t end_idx, BufferWritable& bw, + FormatOptions& options) const { + SERIALIZE_COLUMN_TO_JSON(); +} + void DataTypeObjectSerDe::write_one_cell_to_jsonb(const IColumn& column, JsonbWriter& result, Arena* mem_pool, int32_t col_id, int64_t row_num) const { diff --git a/be/src/vec/data_types/serde/data_type_object_serde.h b/be/src/vec/data_types/serde/data_type_object_serde.h index 4ba144760fb94e..61545ddcc3cb51 100644 --- a/be/src/vec/data_types/serde/data_type_object_serde.h +++ b/be/src/vec/data_types/serde/data_type_object_serde.h @@ -42,9 +42,8 @@ class DataTypeObjectSerDe : public DataTypeSerDe { FormatOptions& options) const override; Status serialize_column_to_json(const IColumn& column, int64_t start_idx, int64_t end_idx, - BufferWritable& bw, FormatOptions& options) const override { - return Status::NotSupported("serialize_column_to_json with type [{}]", column.get_name()); - } + BufferWritable& bw, FormatOptions& options) const override; + Status deserialize_one_cell_from_json(IColumn& column, Slice& slice, const FormatOptions& options) const override { return Status::NotSupported("deserialize_one_cell_from_text with type " + diff --git a/be/src/vec/functions/function_cast.h b/be/src/vec/functions/function_cast.h index ab852b609becd7..f248840199976b 100644 --- a/be/src/vec/functions/function_cast.h +++ b/be/src/vec/functions/function_cast.h @@ -1888,7 +1888,8 @@ class FunctionCast final : public IFunctionBase { variant.is_scalar_variant() || (!variant.is_null_root() && !WhichDataType(remove_nullable(variant.get_root_type())).is_nothing() && - !WhichDataType(data_type_to).is_string()); + !WhichDataType(data_type_to).is_string() && + !WhichDataType(data_type_to).is_json()); if (is_root_valuable) { ColumnPtr nested = variant.get_root(); auto nested_from_type = variant.get_root_type(); @@ -1920,13 +1921,19 @@ class FunctionCast final : public IFunctionBase { // TODO not found root cause, a tmp fix col_to->assume_mutable()->insert_many_defaults(input_rows_count); col_to = make_nullable(col_to, true); + } else if (WhichDataType(data_type_to).is_string()) { + // serialize to string + return ConvertImplGenericToString::execute2(context, block, arguments, result, + input_rows_count); + } else if (WhichDataType(data_type_to).is_json()) { + // serialize to json by parsing + return ConvertImplGenericToJsonb::execute(context, block, arguments, result, + input_rows_count); } else if (!data_type_to->is_nullable() && !WhichDataType(data_type_to).is_string()) { + // other types col_to->assume_mutable()->insert_many_defaults(input_rows_count); col_to = make_nullable(col_to, true); - } else if (WhichDataType(data_type_to).is_string()) { - return ConvertImplGenericToString::execute2(context, block, arguments, result, - input_rows_count); } else { assert_cast(*col_to->assume_mutable()) .insert_many_defaults(input_rows_count); diff --git a/regression-test/data/variant_p0/cast.out b/regression-test/data/variant_p0/cast.out new file mode 100644 index 00000000000000..7ceb039ea71c8d --- /dev/null +++ b/regression-test/data/variant_p0/cast.out @@ -0,0 +1,25 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sql1 -- +{"a":1} + +-- !sql2 -- +int + +-- !sql3 -- +{"aaa":1} + +-- !sql4 -- +[1] + +-- !sql5 -- +123 + +-- !sql6 -- +{"aaa":1} + +-- !sql7 -- +[1] + +-- !sql8 -- +123 + diff --git a/regression-test/suites/variant_p0/cast.groovy b/regression-test/suites/variant_p0/cast.groovy new file mode 100644 index 00000000000000..76c4c134d61e2d --- /dev/null +++ b/regression-test/suites/variant_p0/cast.groovy @@ -0,0 +1,60 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_variant_cast", "p0") { + qt_sql1 """select cast(cast('{"a" : 1}' as variant) as jsonb);""" + qt_sql2 """select json_type(cast(cast('{"a" : 1}' as variant) as jsonb), "\$.a");""" + sql "DROP TABLE IF EXISTS var_cast" + sql """ + CREATE TABLE `var_cast` ( + `k` int NULL, + `var` variant NULL + ) ENGINE=OLAP + UNIQUE KEY(`k`) + DISTRIBUTED BY HASH(k) BUCKETS 1 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + ); + """ + sql """insert into var_cast values (1, '{"aaa" : 1}')""" + qt_sql3 "select cast(var as json) from var_cast" + sql """insert into var_cast values (1, '[1]')""" + qt_sql4 "select cast(var as json) from var_cast" + sql """insert into var_cast values (1, '123')""" + qt_sql5 "select cast(var as json) from var_cast" + + sql "DROP TABLE IF EXISTS var_not_null_cast" + sql """ + CREATE TABLE `var_not_null_cast` ( + `k` int NULL, + `var` variant NOT NULL + ) ENGINE=OLAP + UNIQUE KEY(`k`) + DISTRIBUTED BY HASH(k) BUCKETS 1 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + ); + """ + sql """insert into var_not_null_cast values (1, '{"aaa" : 1}')""" + qt_sql6 "select cast(var as json) from var_not_null_cast" + sql """insert into var_not_null_cast values (1, '[1]')""" + qt_sql7 "select cast(var as json) from var_not_null_cast" + sql """insert into var_not_null_cast values (1, '123')""" + qt_sql8 "select cast(var as json) from var_not_null_cast" +}