diff --git a/be/src/olap/rowset/segment_v2/column_reader.cpp b/be/src/olap/rowset/segment_v2/column_reader.cpp index 9079118ecd18a6..6cd0333028a01c 100644 --- a/be/src/olap/rowset/segment_v2/column_reader.cpp +++ b/be/src/olap/rowset/segment_v2/column_reader.cpp @@ -1117,8 +1117,16 @@ Status DefaultValueColumnIterator::init(const ColumnIteratorOptions& opts) { ((Slice*)_mem_value.data())->size = _default_value.length(); ((Slice*)_mem_value.data())->data = _default_value.data(); } else if (_type_info->type() == OLAP_FIELD_TYPE_ARRAY) { - // TODO llj for Array default value - return Status::NotSupported("Array default type is unsupported"); + if (_default_value != "[]") { + return Status::NotSupported("Array default {} is unsupported", _default_value); + } else { + ((Slice*)_mem_value.data())->size = _default_value.length(); + ((Slice*)_mem_value.data())->data = _default_value.data(); + } + } else if (_type_info->type() == OLAP_FIELD_TYPE_STRUCT) { + return Status::NotSupported("STRUCT default type is unsupported"); + } else if (_type_info->type() == OLAP_FIELD_TYPE_MAP) { + return Status::NotSupported("MAP default type is unsupported"); } else { s = _type_info->from_string(_mem_value.data(), _default_value, _precision, _scale); } @@ -1139,9 +1147,6 @@ Status DefaultValueColumnIterator::init(const ColumnIteratorOptions& opts) { void DefaultValueColumnIterator::insert_default_data(const TypeInfo* type_info, size_t type_size, void* mem_value, vectorized::MutableColumnPtr& dst, size_t n) { - vectorized::Int128 int128; - char* data_ptr = (char*)&int128; - size_t data_len = sizeof(int128); dst = dst->convert_to_predicate_column_if_dictionary(); switch (type_info->type()) { @@ -1151,18 +1156,26 @@ void DefaultValueColumnIterator::insert_default_data(const TypeInfo* type_info, break; } case OLAP_FIELD_TYPE_DATE: { + vectorized::Int64 int64; + char* data_ptr = (char*)&int64; + size_t data_len = sizeof(int64); + assert(type_size == sizeof(FieldTypeTraits::CppType)); //uint24_t std::string str = FieldTypeTraits::to_string(mem_value); vectorized::VecDateTimeValue value; value.from_date_str(str.c_str(), str.length()); value.cast_to_date(); - //TODO: here is int128 = int64, here rely on the logic of little endian - int128 = binary_cast(value); + + int64 = binary_cast(value); dst->insert_many_data(data_ptr, data_len, n); break; } case OLAP_FIELD_TYPE_DATETIME: { + vectorized::Int64 int64; + char* data_ptr = (char*)&int64; + size_t data_len = sizeof(int64); + assert(type_size == sizeof(FieldTypeTraits::CppType)); //int64_t std::string str = FieldTypeTraits::to_string(mem_value); @@ -1170,11 +1183,15 @@ void DefaultValueColumnIterator::insert_default_data(const TypeInfo* type_info, value.from_date_str(str.c_str(), str.length()); value.to_datetime(); - int128 = binary_cast(value); + int64 = binary_cast(value); dst->insert_many_data(data_ptr, data_len, n); break; } case OLAP_FIELD_TYPE_DECIMAL: { + vectorized::Int128 int128; + char* data_ptr = (char*)&int128; + size_t data_len = sizeof(int128); + assert(type_size == sizeof(FieldTypeTraits::CppType)); //decimal12_t decimal12_t* d = (decimal12_t*)mem_value; @@ -1186,14 +1203,22 @@ void DefaultValueColumnIterator::insert_default_data(const TypeInfo* type_info, case OLAP_FIELD_TYPE_VARCHAR: case OLAP_FIELD_TYPE_CHAR: case OLAP_FIELD_TYPE_JSONB: { - data_ptr = ((Slice*)mem_value)->data; - data_len = ((Slice*)mem_value)->size; + char* data_ptr = ((Slice*)mem_value)->data; + size_t data_len = ((Slice*)mem_value)->size; dst->insert_many_data(data_ptr, data_len, n); break; } + case OLAP_FIELD_TYPE_ARRAY: { + if (dst->is_nullable()) { + static_cast(*dst).insert_not_null_elements(n); + } else { + dst->insert_many_defaults(n); + } + break; + } default: { - data_ptr = (char*)mem_value; - data_len = type_size; + char* data_ptr = (char*)mem_value; + size_t data_len = type_size; dst->insert_many_data(data_ptr, data_len, n); } } diff --git a/be/src/vec/columns/column_nullable.h b/be/src/vec/columns/column_nullable.h index c48e3c80a18eed..d9216cde49e9d6 100644 --- a/be/src/vec/columns/column_nullable.h +++ b/be/src/vec/columns/column_nullable.h @@ -153,6 +153,12 @@ class ColumnNullable final : public COWHelper { _has_null = true; } + void insert_not_null_elements(size_t num) { + get_nested_column().insert_many_defaults(num); + _get_null_map_column().fill(0, num); + _has_null = false; + } + void insert_null_elements(int num) { get_nested_column().insert_many_defaults(num); _get_null_map_column().fill(1, num); diff --git a/regression-test/data/schema_change_p0/test_alter_table_column.out b/regression-test/data/schema_change_p0/test_alter_table_column.out index a130d16e16e71b..81a715c2bcdd22 100644 --- a/regression-test/data/schema_change_p0/test_alter_table_column.out +++ b/regression-test/data/schema_change_p0/test_alter_table_column.out @@ -18,6 +18,17 @@ value2 INT Yes false \N SUM -- !sql -- 1 1 40 60 +-- !sql -- +k1 INT Yes true \N +value1 INT Yes false \N NONE +value2 ARRAY Yes false [] NONE +value3 ARRAY Yes false \N NONE +value4 ARRAY No false [] NONE + +-- !sql -- +1 2 [] \N [] +3 4 [] \N [] + -- !select -- \N \N \N 1 1989 1001 diff --git a/regression-test/suites/schema_change_p0/test_alter_table_column.groovy b/regression-test/suites/schema_change_p0/test_alter_table_column.groovy index e6848dc7fefec6..56fb531074935b 100644 --- a/regression-test/suites/schema_change_p0/test_alter_table_column.groovy +++ b/regression-test/suites/schema_change_p0/test_alter_table_column.groovy @@ -114,6 +114,47 @@ suite("test_alter_table_column") { qt_sql "select * from ${tbName2};" sql "DROP TABLE ${tbName2} FORCE;" + def tbNameAddArray = "alter_table_add_array_column_dup" + sql "DROP TABLE IF EXISTS ${tbNameAddArray}" + sql """ + CREATE TABLE IF NOT EXISTS ${tbNameAddArray} ( + k1 INT, + value1 INT + ) + DUPLICATE KEY (k1) + DISTRIBUTED BY HASH(k1) BUCKETS 5 properties( + "replication_num" = "1", + "light_schema_change" = "true", + "disable_auto_compaction" = "true"); + """ + + sql "insert into ${tbNameAddArray} values(1,2)" + sql "insert into ${tbNameAddArray} values(3,4)" + sql """ + ALTER TABLE ${tbNameAddArray} + ADD COLUMN value2 ARRAY DEFAULT '[]' AFTER value1, + ADD COLUMN value3 ARRAY AFTER value2, + ADD COLUMN value4 ARRAY NOT NULL DEFAULT '[]' AFTER value3; + """ + max_try_secs = 60 + while (max_try_secs--) { + String res = getJobState(tbNameAddArray) + if (res == "FINISHED") { + break + } else { + Thread.sleep(2000) + if (max_try_secs < 1) { + println "test timeout," + "state:" + res + assertEquals("FINISHED",res) + } + } + } + + Thread.sleep(200) + qt_sql "desc ${tbNameAddArray};" + qt_sql "select * from ${tbNameAddArray};" + sql "DROP TABLE ${tbNameAddArray} FORCE;" + // vector search def check_load_result = {checklabel, testTablex -> Integer max_try_milli_secs = 10000 @@ -175,4 +216,5 @@ suite("test_alter_table_column") { def res4 = sql "select k1, k2, k3, null from baseall order by k1" check2_doris(res3, res4) sql "DROP TABLE ${tbName3} FORCE;" + }