This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new b5531c5caf [BugFix](BE) fix condition index doesn't match (#11474)
b5531c5caf is described below
commit b5531c5cafec76501617705c7395d31225474897
Author: Lightman <[email protected]>
AuthorDate: Fri Aug 5 07:57:18 2022 +0800
[BugFix](BE) fix condition index doesn't match (#11474)
* [BugFix](Be) fix condition index doesn't match
---
be/src/olap/bloom_filter_predicate.h | 4 +-
be/src/olap/column_predicate.h | 3 +-
be/src/olap/comparison_predicate.h | 5 +-
be/src/olap/field.h | 6 +-
be/src/olap/in_list_predicate.h | 5 +-
be/src/olap/like_column_predicate.h | 4 +-
be/src/olap/null_predicate.cpp | 9 +-
be/src/olap/null_predicate.h | 4 +-
be/src/olap/olap_cond.cpp | 8 +-
be/src/olap/reader.cpp | 5 +-
be/src/olap/rowset/beta_rowset_reader.cpp | 1 -
be/src/olap/rowset/segment_v2/segment.cpp | 2 +-
be/src/olap/rowset/segment_v2/segment_iterator.cpp | 67 +++---
be/src/olap/rowset/segment_v2/segment_iterator.h | 8 +-
be/src/olap/schema.h | 11 +
be/src/olap/tablet_schema.cpp | 1 +
.../schema_change/test_uniq_keys_schema_change.out | 22 ++
.../schema_change/test_uniq_mv_schema_change.out | 25 +++
.../test_uniq_rollup_schema_change.out | 24 +++
.../schema_change/test_uniq_vals_schema_change.out | 22 ++
.../schema_change/test_update_schema_change.out | 64 ++++++
.../test_agg_keys_schema_change.groovy | 4 +-
.../schema_change/test_agg_mv_schema_change.groovy | 2 +-
.../test_agg_rollup_schema_change.groovy | 2 +-
.../schema_change/test_alter_table_column.groovy | 2 +-
.../test_alter_table_column_with_delete.groovy | 2 +-
.../test_dup_keys_schema_change.groovy | 2 +-
.../schema_change/test_dup_mv_schema_change.groovy | 2 +-
.../suites/schema_change/test_schema_change.groovy | 2 +-
.../test_uniq_keys_schema_change.groovy | 203 ++++++++++++++++++
.../test_uniq_mv_schema_change.groovy | 226 ++++++++++++++++++++
.../test_uniq_rollup_schema_change.groovy | 237 +++++++++++++++++++++
....groovy => test_uniq_vals_schema_change.groovy} | 51 ++---
.../schema_change/test_update_schema_change.sql | 50 +++++
34 files changed, 980 insertions(+), 105 deletions(-)
diff --git a/be/src/olap/bloom_filter_predicate.h
b/be/src/olap/bloom_filter_predicate.h
index e5833729b4..b1b4217ace 100644
--- a/be/src/olap/bloom_filter_predicate.h
+++ b/be/src/olap/bloom_filter_predicate.h
@@ -52,8 +52,8 @@ public:
void evaluate_and(ColumnBlock* block, uint16_t* sel, uint16_t size,
bool* flags) const override {};
- Status evaluate(const Schema& schema, const vector<BitmapIndexIterator*>&
iterators,
- uint32_t num_rows, roaring::Roaring* roaring) const
override {
+ Status evaluate(BitmapIndexIterator* iterators, uint32_t num_rows,
+ roaring::Roaring* roaring) const override {
return Status::OK();
}
diff --git a/be/src/olap/column_predicate.h b/be/src/olap/column_predicate.h
index 2edf19d6da..d88b3c825f 100644
--- a/be/src/olap/column_predicate.h
+++ b/be/src/olap/column_predicate.h
@@ -82,8 +82,7 @@ public:
bool* flags) const = 0;
//evaluate predicate on Bitmap
- virtual Status evaluate(const Schema& schema,
- const std::vector<BitmapIndexIterator*>&
iterators, uint32_t num_rows,
+ virtual Status evaluate(BitmapIndexIterator* iterator, uint32_t num_rows,
roaring::Roaring* roaring) const = 0;
// evaluate predicate on IColumn
diff --git a/be/src/olap/comparison_predicate.h
b/be/src/olap/comparison_predicate.h
index ec8bcce1f5..1ba25e5db2 100644
--- a/be/src/olap/comparison_predicate.h
+++ b/be/src/olap/comparison_predicate.h
@@ -110,9 +110,8 @@ public:
}
}
- Status evaluate(const Schema& schema, const
std::vector<BitmapIndexIterator*>& iterators,
- uint32_t num_rows, roaring::Roaring* bitmap) const
override {
- BitmapIndexIterator* iterator = iterators[_column_id];
+ Status evaluate(BitmapIndexIterator* iterator, uint32_t num_rows,
+ roaring::Roaring* bitmap) const override {
if (iterator == nullptr) {
return Status::OK();
}
diff --git a/be/src/olap/field.h b/be/src/olap/field.h
index 99b9bc0665..5f49bb9b2c 100644
--- a/be/src/olap/field.h
+++ b/be/src/olap/field.h
@@ -47,7 +47,8 @@ public:
_key_coder(get_key_coder(column.type())),
_name(column.name()),
_index_size(column.index_length()),
- _is_nullable(column.is_nullable()) {
+ _is_nullable(column.is_nullable()),
+ _unique_id(column.unique_id()) {
if (column.type() == OLAP_FIELD_TYPE_ARRAY) {
_agg_info = get_aggregate_info(column.aggregation(), column.type(),
column.get_sub_column(0).type());
@@ -62,6 +63,7 @@ public:
int32_t length() const { return _length; }
size_t field_size() const { return size() + 1; }
size_t index_size() const { return _index_size; }
+ int32_t unique_id() const { return _unique_id; }
const std::string& name() const { return _name; }
virtual void set_to_max(char* buf) const { return
_type_info->set_to_max(buf); }
@@ -334,6 +336,7 @@ protected:
other->_sub_fields.clear();
other->_precision = this->_precision;
other->_scale = this->_scale;
+ other->_unique_id = this->_unique_id;
for (const auto& f : _sub_fields) {
Field* item = f->clone();
other->add_sub_field(std::unique_ptr<Field>(item));
@@ -350,6 +353,7 @@ private:
std::vector<std::unique_ptr<Field>> _sub_fields;
int32_t _precision;
int32_t _scale;
+ int32_t _unique_id;
};
template <typename LhsCellType, typename RhsCellType>
diff --git a/be/src/olap/in_list_predicate.h b/be/src/olap/in_list_predicate.h
index 3d22ecb83f..35b4c4162e 100644
--- a/be/src/olap/in_list_predicate.h
+++ b/be/src/olap/in_list_predicate.h
@@ -110,9 +110,8 @@ public:
}
}
- Status evaluate(const Schema& schema, const
std::vector<BitmapIndexIterator*>& iterators,
- uint32_t num_rows, roaring::Roaring* result) const
override {
- BitmapIndexIterator* iterator = iterators[_column_id];
+ Status evaluate(BitmapIndexIterator* iterator, uint32_t num_rows,
+ roaring::Roaring* result) const override {
if (iterator == nullptr) {
return Status::OK();
}
diff --git a/be/src/olap/like_column_predicate.h
b/be/src/olap/like_column_predicate.h
index b72846ff5f..fb00f7b146 100644
--- a/be/src/olap/like_column_predicate.h
+++ b/be/src/olap/like_column_predicate.h
@@ -40,8 +40,8 @@ public:
}
void evaluate_and(ColumnBlock* block, uint16_t* sel, uint16_t size,
bool* flags) const override {}
- Status evaluate(const Schema& schema, const
std::vector<BitmapIndexIterator*>& iterators,
- uint32_t num_rows, roaring::Roaring* roaring) const
override {
+ Status evaluate(BitmapIndexIterator* iterator, uint32_t num_rows,
+ roaring::Roaring* roaring) const override {
return Status::OK();
}
diff --git a/be/src/olap/null_predicate.cpp b/be/src/olap/null_predicate.cpp
index d755fd34eb..ade037374e 100644
--- a/be/src/olap/null_predicate.cpp
+++ b/be/src/olap/null_predicate.cpp
@@ -72,12 +72,11 @@ void NullPredicate::evaluate_and(ColumnBlock* block,
uint16_t* sel, uint16_t siz
}
}
-Status NullPredicate::evaluate(const Schema& schema,
- const std::vector<BitmapIndexIterator*>&
iterators,
- uint32_t num_rows, roaring::Roaring* roaring)
const {
- if (iterators[_column_id] != nullptr) {
+Status NullPredicate::evaluate(BitmapIndexIterator* iterator, uint32_t
num_rows,
+ roaring::Roaring* roaring) const {
+ if (iterator != nullptr) {
roaring::Roaring null_bitmap;
- RETURN_IF_ERROR(iterators[_column_id]->read_null_bitmap(&null_bitmap));
+ RETURN_IF_ERROR(iterator->read_null_bitmap(&null_bitmap));
if (_is_null) {
*roaring &= null_bitmap;
} else {
diff --git a/be/src/olap/null_predicate.h b/be/src/olap/null_predicate.h
index caf05af16d..a42e576caf 100644
--- a/be/src/olap/null_predicate.h
+++ b/be/src/olap/null_predicate.h
@@ -37,8 +37,8 @@ public:
void evaluate_and(ColumnBlock* block, uint16_t* sel, uint16_t size, bool*
flags) const override;
- Status evaluate(const Schema& schema, const vector<BitmapIndexIterator*>&
iterators,
- uint32_t num_rows, roaring::Roaring* roaring) const
override;
+ Status evaluate(BitmapIndexIterator* iterator, uint32_t num_rows,
+ roaring::Roaring* roaring) const override;
uint16_t evaluate(const vectorized::IColumn& column, uint16_t* sel,
uint16_t size) const override;
diff --git a/be/src/olap/olap_cond.cpp b/be/src/olap/olap_cond.cpp
index 627f846092..02e818331b 100644
--- a/be/src/olap/olap_cond.cpp
+++ b/be/src/olap/olap_cond.cpp
@@ -550,10 +550,10 @@ Status Conditions::append_condition(const TCondition&
tcond) {
}
CondColumn* cond_col = nullptr;
- auto it = _columns.find(index);
+ auto it = _columns.find(column.unique_id());
if (it == _columns.end()) {
cond_col = new CondColumn(*_schema, index);
- _columns[index] = cond_col;
+ _columns[column.unique_id()] = cond_col;
} else {
cond_col = it->second;
}
@@ -561,8 +561,8 @@ Status Conditions::append_condition(const TCondition&
tcond) {
return cond_col->add_cond(tcond, column);
}
-CondColumn* Conditions::get_column(int32_t cid) const {
- auto iter = _columns.find(cid);
+CondColumn* Conditions::get_column(int32_t uid) const {
+ auto iter = _columns.find(uid);
if (iter != _columns.end()) {
return iter->second;
}
diff --git a/be/src/olap/reader.cpp b/be/src/olap/reader.cpp
index 49c1e11d60..50f4e7178a 100644
--- a/be/src/olap/reader.cpp
+++ b/be/src/olap/reader.cpp
@@ -549,13 +549,14 @@ void TabletReader::_init_load_bf_columns(const
ReaderParams& read_params, Condit
std::set<uint32_t>* load_bf_columns) {
// add all columns with condition to load_bf_columns
for (const auto& cond_column : conditions->columns()) {
- if (!_tablet_schema->column(cond_column.first).is_bf_column()) {
+ int32_t column_id = _tablet_schema->field_index(cond_column.first);
+ if (!_tablet_schema->column(column_id).is_bf_column()) {
continue;
}
for (const auto& cond : cond_column.second->conds()) {
if (cond->op == OP_EQ ||
(cond->op == OP_IN && cond->operand_set.size() <
MAX_OP_IN_FIELD_NUM)) {
- load_bf_columns->insert(cond_column.first);
+ load_bf_columns->insert(column_id);
}
}
}
diff --git a/be/src/olap/rowset/beta_rowset_reader.cpp
b/be/src/olap/rowset/beta_rowset_reader.cpp
index accd4b9859..b96255d16f 100644
--- a/be/src/olap/rowset/beta_rowset_reader.cpp
+++ b/be/src/olap/rowset/beta_rowset_reader.cpp
@@ -72,7 +72,6 @@ Status BetaRowsetReader::init(RowsetReaderContext*
read_context) {
read_context->predicates->begin(),
read_context->predicates->end());
}
-
// Take a delete-bitmap for each segment, the bitmap contains all deletes
// until the max read version, which is read_context->version.second
if (read_context->delete_bitmap != nullptr) {
diff --git a/be/src/olap/rowset/segment_v2/segment.cpp
b/be/src/olap/rowset/segment_v2/segment.cpp
index 735ae3c4e9..d042e4f7ef 100644
--- a/be/src/olap/rowset/segment_v2/segment.cpp
+++ b/be/src/olap/rowset/segment_v2/segment.cpp
@@ -80,7 +80,7 @@ Status Segment::new_iterator(const Schema& schema, const
StorageReadOptions& rea
// trying to prune the current segment by segment-level zone map
if (read_options.conditions != nullptr) {
for (auto& column_condition : read_options.conditions->columns()) {
- int32_t column_unique_id =
_tablet_schema->column(column_condition.first).unique_id();
+ int32_t column_unique_id = column_condition.first;
if (_column_readers.count(column_unique_id) < 1 ||
!_column_readers.at(column_unique_id)->has_zone_map()) {
continue;
diff --git a/be/src/olap/rowset/segment_v2/segment_iterator.cpp
b/be/src/olap/rowset/segment_v2/segment_iterator.cpp
index 1b39703863..0566e29b15 100644
--- a/be/src/olap/rowset/segment_v2/segment_iterator.cpp
+++ b/be/src/olap/rowset/segment_v2/segment_iterator.cpp
@@ -107,8 +107,6 @@ private:
SegmentIterator::SegmentIterator(std::shared_ptr<Segment> segment, const
Schema& schema)
: _segment(std::move(segment)),
_schema(schema),
- _column_iterators(_schema.num_columns(), nullptr),
- _bitmap_index_iterators(_schema.num_columns(), nullptr),
_cur_rowid(0),
_lazy_materialization_read(false),
_inited(false),
@@ -116,10 +114,10 @@ SegmentIterator::SegmentIterator(std::shared_ptr<Segment>
segment, const Schema&
SegmentIterator::~SegmentIterator() {
for (auto iter : _column_iterators) {
- delete iter;
+ delete iter.second;
}
for (auto iter : _bitmap_index_iterators) {
- delete iter;
+ delete iter.second;
}
}
@@ -222,13 +220,14 @@ Status SegmentIterator::_prepare_seek(const
StorageReadOptions::KeyRange& key_ra
// create used column iterator
for (auto cid : _seek_schema->column_ids()) {
- if (_column_iterators[cid] == nullptr) {
+ int32_t unique_id = _opts.tablet_schema->column(cid).unique_id();
+ if (_column_iterators.count(unique_id) < 1) {
RETURN_IF_ERROR(_segment->new_column_iterator(_opts.tablet_schema->column(cid),
-
&_column_iterators[cid]));
+
&_column_iterators[unique_id]));
ColumnIteratorOptions iter_opts;
iter_opts.stats = _opts.stats;
iter_opts.file_reader = _file_reader.get();
- RETURN_IF_ERROR(_column_iterators[cid]->init(iter_opts));
+ RETURN_IF_ERROR(_column_iterators[unique_id]->init(iter_opts));
}
}
@@ -256,21 +255,21 @@ Status
SegmentIterator::_get_row_ranges_by_column_conditions() {
}
Status SegmentIterator::_get_row_ranges_from_conditions(RowRanges*
condition_row_ranges) {
- std::set<int32_t> cids;
+ std::set<int32_t> uids;
if (_opts.conditions != nullptr) {
for (auto& column_condition : _opts.conditions->columns()) {
- cids.insert(column_condition.first);
+ uids.insert(column_condition.first);
}
}
// first filter data by bloom filter index
// bloom filter index only use CondColumn
RowRanges bf_row_ranges = RowRanges::create_single(num_rows());
- for (auto& cid : cids) {
+ for (auto& uid : uids) {
// get row ranges by bf index of this column,
RowRanges column_bf_row_ranges = RowRanges::create_single(num_rows());
- CondColumn* column_cond = _opts.conditions->get_column(cid);
- RETURN_IF_ERROR(_column_iterators[cid]->get_row_ranges_by_bloom_filter(
+ CondColumn* column_cond = _opts.conditions->get_column(uid);
+ RETURN_IF_ERROR(_column_iterators[uid]->get_row_ranges_by_bloom_filter(
column_cond, &column_bf_row_ranges));
RowRanges::ranges_intersection(bf_row_ranges, column_bf_row_ranges,
&bf_row_ranges);
}
@@ -280,14 +279,14 @@ Status
SegmentIterator::_get_row_ranges_from_conditions(RowRanges* condition_row
RowRanges zone_map_row_ranges = RowRanges::create_single(num_rows());
// second filter data by zone map
- for (auto& cid : cids) {
+ for (auto& uid : uids) {
// get row ranges by zone map of this column,
RowRanges column_row_ranges = RowRanges::create_single(num_rows());
CondColumn* column_cond = nullptr;
if (_opts.conditions != nullptr) {
- column_cond = _opts.conditions->get_column(cid);
+ column_cond = _opts.conditions->get_column(uid);
}
-
RETURN_IF_ERROR(_column_iterators[cid]->get_row_ranges_by_zone_map(column_cond,
nullptr,
+
RETURN_IF_ERROR(_column_iterators[uid]->get_row_ranges_by_zone_map(column_cond,
nullptr,
&column_row_ranges));
// intersect different columns's row ranges to get final row ranges by
zone map
RowRanges::ranges_intersection(zone_map_row_ranges, column_row_ranges,
@@ -298,13 +297,13 @@ Status
SegmentIterator::_get_row_ranges_from_conditions(RowRanges* condition_row
for (auto& delete_condition : _opts.delete_conditions) {
RowRanges delete_condition_row_ranges = RowRanges::create_single(0);
for (auto& delete_column_condition : delete_condition->columns()) {
- const int32_t cid = delete_column_condition.first;
+ const int32_t uid = delete_column_condition.first;
CondColumn* column_cond = nullptr;
if (_opts.conditions != nullptr) {
- column_cond = _opts.conditions->get_column(cid);
+ column_cond = _opts.conditions->get_column(uid);
}
RowRanges single_delete_condition_row_ranges =
RowRanges::create_single(num_rows());
- RETURN_IF_ERROR(_column_iterators[cid]->get_row_ranges_by_zone_map(
+ RETURN_IF_ERROR(_column_iterators[uid]->get_row_ranges_by_zone_map(
column_cond, delete_column_condition.second,
&single_delete_condition_row_ranges));
RowRanges::ranges_union(delete_condition_row_ranges,
single_delete_condition_row_ranges,
@@ -329,11 +328,13 @@ Status SegmentIterator::_apply_bitmap_index() {
std::vector<ColumnPredicate*> remaining_predicates;
for (auto pred : _col_predicates) {
- if (_bitmap_index_iterators[pred->column_id()] == nullptr) {
+ int32_t unique_id = _schema.unique_id(pred->column_id());
+ if (_bitmap_index_iterators.count(unique_id) < 1 ||
+ _bitmap_index_iterators[unique_id] == nullptr) {
// no bitmap index for this column
remaining_predicates.push_back(pred);
} else {
- RETURN_IF_ERROR(pred->evaluate(_schema, _bitmap_index_iterators,
_segment->num_rows(),
+ RETURN_IF_ERROR(pred->evaluate(_bitmap_index_iterators[unique_id],
_segment->num_rows(),
&_row_bitmap));
if (_row_bitmap.isEmpty()) {
break; // all rows have been pruned, no need to process
further predicates
@@ -350,14 +351,15 @@ Status SegmentIterator::_init_return_column_iterators() {
return Status::OK();
}
for (auto cid : _schema.column_ids()) {
- if (_column_iterators[cid] == nullptr) {
+ int32_t unique_id = _opts.tablet_schema->column(cid).unique_id();
+ if (_column_iterators.count(unique_id) < 1) {
RETURN_IF_ERROR(_segment->new_column_iterator(_opts.tablet_schema->column(cid),
-
&_column_iterators[cid]));
+
&_column_iterators[unique_id]));
ColumnIteratorOptions iter_opts;
iter_opts.stats = _opts.stats;
iter_opts.use_page_cache = _opts.use_page_cache;
iter_opts.file_reader = _file_reader.get();
- RETURN_IF_ERROR(_column_iterators[cid]->init(iter_opts));
+ RETURN_IF_ERROR(_column_iterators[unique_id]->init(iter_opts));
}
}
return Status::OK();
@@ -368,9 +370,10 @@ Status SegmentIterator::_init_bitmap_index_iterators() {
return Status::OK();
}
for (auto cid : _schema.column_ids()) {
- if (_bitmap_index_iterators[cid] == nullptr) {
-
RETURN_IF_ERROR(_segment->new_bitmap_index_iterator(_opts.tablet_schema->column(cid),
-
&_bitmap_index_iterators[cid]));
+ int32_t unique_id = _opts.tablet_schema->column(cid).unique_id();
+ if (_bitmap_index_iterators.count(unique_id) < 1) {
+ RETURN_IF_ERROR(_segment->new_bitmap_index_iterator(
+ _opts.tablet_schema->column(cid),
&_bitmap_index_iterators[unique_id]));
}
}
return Status::OK();
@@ -541,7 +544,7 @@ void SegmentIterator::_init_lazy_materialization() {
Status SegmentIterator::_seek_columns(const std::vector<ColumnId>& column_ids,
rowid_t pos) {
for (auto cid : column_ids) {
- RETURN_IF_ERROR(_column_iterators[cid]->seek_to_ordinal(pos));
+
RETURN_IF_ERROR(_column_iterators[_schema.unique_id(cid)]->seek_to_ordinal(pos));
}
return Status::OK();
}
@@ -552,7 +555,7 @@ Status SegmentIterator::_read_columns(const
std::vector<ColumnId>& column_ids, R
auto column_block = block->column_block(cid);
ColumnBlockView dst(&column_block, row_offset);
size_t rows_read = nrows;
- RETURN_IF_ERROR(_column_iterators[cid]->next_batch(&rows_read, &dst));
+
RETURN_IF_ERROR(_column_iterators[_schema.unique_id(cid)]->next_batch(&rows_read,
&dst));
DCHECK_EQ(nrows, rows_read);
}
return Status::OK();
@@ -809,7 +812,7 @@ bool
SegmentIterator::_can_evaluated_by_vectorized(ColumnPredicate* predicate) {
if (field_type == OLAP_FIELD_TYPE_VARCHAR || field_type ==
OLAP_FIELD_TYPE_CHAR ||
field_type == OLAP_FIELD_TYPE_STRING) {
return config::enable_low_cardinality_optimize &&
- _column_iterators[cid]->is_all_dict_encoding();
+
_column_iterators[_schema.unique_id(cid)]->is_all_dict_encoding();
} else if (field_type == OLAP_FIELD_TYPE_DECIMAL) {
return false;
}
@@ -836,7 +839,7 @@ Status SegmentIterator::_read_columns(const
std::vector<ColumnId>& column_ids,
for (auto cid : column_ids) {
auto& column = column_block[cid];
size_t rows_read = nrows;
- RETURN_IF_ERROR(_column_iterators[cid]->next_batch(&rows_read,
column));
+
RETURN_IF_ERROR(_column_iterators[_schema.unique_id(cid)]->next_batch(&rows_read,
column));
DCHECK_EQ(nrows, rows_read);
}
return Status::OK();
@@ -1008,8 +1011,8 @@ Status
SegmentIterator::_read_columns_by_rowids(std::vector<ColumnId>& read_colu
rowids[i] = rowid_vector[sel_rowid_idx[i]];
}
for (auto cid : read_column_ids) {
- RETURN_IF_ERROR(_column_iterators[cid]->read_by_rowids(rowids.data(),
select_size,
-
_current_return_columns[cid]));
+
RETURN_IF_ERROR(_column_iterators[_schema.unique_id(cid)]->read_by_rowids(
+ rowids.data(), select_size, _current_return_columns[cid]));
}
return Status::OK();
diff --git a/be/src/olap/rowset/segment_v2/segment_iterator.h
b/be/src/olap/rowset/segment_v2/segment_iterator.h
index 7170d60108..76ad8f3ff5 100644
--- a/be/src/olap/rowset/segment_v2/segment_iterator.h
+++ b/be/src/olap/rowset/segment_v2/segment_iterator.h
@@ -164,10 +164,10 @@ private:
std::shared_ptr<Segment> _segment;
const Schema& _schema;
// _column_iterators.size() == _schema.num_columns()
- // _column_iterators[cid] == nullptr if cid is not in _schema
- std::vector<ColumnIterator*> _column_iterators;
- // FIXME prefer vector<unique_ptr<BitmapIndexIterator>>
- std::vector<BitmapIndexIterator*> _bitmap_index_iterators;
+ // map<unique_id, ColumnIterator*>
_column_iterators/_bitmap_index_iterators;
+ // can use _schema get unique_id by cid
+ std::map<int32_t, ColumnIterator*> _column_iterators;
+ std::map<int32_t, BitmapIndexIterator*> _bitmap_index_iterators;
// after init(), `_row_bitmap` contains all rowid to scan
roaring::Roaring _row_bitmap;
// an iterator for `_row_bitmap` that can be used to extract row range to
scan
diff --git a/be/src/olap/schema.h b/be/src/olap/schema.h
index a36547e475..a93a12432f 100644
--- a/be/src/olap/schema.h
+++ b/be/src/olap/schema.h
@@ -40,6 +40,7 @@ public:
Schema(const TabletSchema& tablet_schema) {
size_t num_columns = tablet_schema.num_columns();
std::vector<ColumnId> col_ids(num_columns);
+ _unique_ids.resize(num_columns);
std::vector<TabletColumn> columns;
columns.reserve(num_columns);
@@ -47,6 +48,7 @@ public:
for (uint32_t cid = 0; cid < num_columns; ++cid) {
col_ids[cid] = cid;
const TabletColumn& column = tablet_schema.column(cid);
+ _unique_ids[cid] = column.unique_id();
if (column.is_key()) {
++num_key_columns;
}
@@ -62,6 +64,7 @@ public:
// All the columns of one table may exist in the columns param, but
col_ids is only a subset.
Schema(const std::vector<TabletColumn>& columns, const
std::vector<ColumnId>& col_ids) {
size_t num_key_columns = 0;
+ _unique_ids.resize(columns.size());
for (size_t i = 0; i < columns.size(); ++i) {
if (columns[i].is_key()) {
++num_key_columns;
@@ -69,6 +72,7 @@ public:
if (columns[i].name() == DELETE_SIGN) {
_delete_sign_idx = i;
}
+ _unique_ids[i] = columns[i].unique_id();
}
_init(columns, col_ids, num_key_columns);
}
@@ -76,8 +80,10 @@ public:
// Only for UT
Schema(const std::vector<TabletColumn>& columns, size_t num_key_columns) {
std::vector<ColumnId> col_ids(columns.size());
+ _unique_ids.resize(columns.size());
for (uint32_t cid = 0; cid < columns.size(); ++cid) {
col_ids[cid] = cid;
+ _unique_ids[cid] = columns[cid].unique_id();
}
_init(columns, col_ids, num_key_columns);
@@ -85,11 +91,13 @@ public:
Schema(const std::vector<const Field*>& cols, size_t num_key_columns) {
std::vector<ColumnId> col_ids(cols.size());
+ _unique_ids.resize(cols.size());
for (uint32_t cid = 0; cid < cols.size(); ++cid) {
col_ids[cid] = cid;
if (cols.at(cid)->name() == DELETE_SIGN) {
_delete_sign_idx = cid;
}
+ _unique_ids[cid] = cols[cid]->unique_id();
}
_init(cols, col_ids, num_key_columns);
@@ -133,7 +141,9 @@ public:
size_t num_columns() const { return _cols.size(); }
size_t num_column_ids() const { return _col_ids.size(); }
const std::vector<ColumnId>& column_ids() const { return _col_ids; }
+ const std::vector<int32_t>& unique_ids() const { return _unique_ids; }
ColumnId column_id(size_t index) const { return _col_ids[index]; }
+ int32_t unique_id(size_t index) const { return _unique_ids[index]; }
int32_t delete_sign_idx() const { return _delete_sign_idx; }
bool has_sequence_col() const { return _has_sequence_col; }
@@ -148,6 +158,7 @@ private:
// NOTE: The ColumnId here represents the sequential index number
(starting from 0) of
// a column in current row, not the unique id-identifier of each column
std::vector<ColumnId> _col_ids;
+ std::vector<int32_t> _unique_ids;
// NOTE: Both _cols[cid] and _col_offsets[cid] can only be accessed when
the cid is
// contained in _col_ids
std::vector<Field*> _cols;
diff --git a/be/src/olap/tablet_schema.cpp b/be/src/olap/tablet_schema.cpp
index 597c5e60f2..b2040f5849 100644
--- a/be/src/olap/tablet_schema.cpp
+++ b/be/src/olap/tablet_schema.cpp
@@ -497,6 +497,7 @@ void TabletSchema::init_from_pb(const TabletSchemaPB&
schema) {
_num_null_columns = 0;
_cols.clear();
_field_name_to_index.clear();
+ _field_id_to_index.clear();
for (auto& column_pb : schema.column()) {
TabletColumn column;
column.init_from_pb(column_pb);
diff --git
a/regression-test/data/schema_change/test_uniq_keys_schema_change.out
b/regression-test/data/schema_change/test_uniq_keys_schema_change.out
new file mode 100644
index 0000000000..ef963eca86
--- /dev/null
+++ b/regression-test/data/schema_change/test_uniq_keys_schema_change.out
@@ -0,0 +1,22 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sc --
+2
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 1
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 2
+
+-- !sc --
+3
+
+-- !sc --
+4 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 2
+
+-- !sc --
+5
+
+-- !sc --
+2 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 1
+
diff --git a/regression-test/data/schema_change/test_uniq_mv_schema_change.out
b/regression-test/data/schema_change/test_uniq_mv_schema_change.out
new file mode 100644
index 0000000000..2835e5c76e
--- /dev/null
+++ b/regression-test/data/schema_change/test_uniq_mv_schema_change.out
@@ -0,0 +1,25 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sc --
+2
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 1
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 2
+
+-- !sc --
+3
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 32 20 2
+
+-- !sc --
+4 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 32 20 2
+
+-- !sc --
+5
+
+-- !sc --
+2 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 32 20 1
+
diff --git
a/regression-test/data/schema_change/test_uniq_rollup_schema_change.out
b/regression-test/data/schema_change/test_uniq_rollup_schema_change.out
new file mode 100644
index 0000000000..b8d58e78c0
--- /dev/null
+++ b/regression-test/data/schema_change/test_uniq_rollup_schema_change.out
@@ -0,0 +1,24 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sc --
+2
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 1
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 2
+
+-- !sc --
+3
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 32 20 2
+
+-- !sc --
+4 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 32 20 2
+
+-- !sc --
+5
+
+-- !sc --
+2 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 32 20 1
\ No newline at end of file
diff --git
a/regression-test/data/schema_change/test_uniq_vals_schema_change.out
b/regression-test/data/schema_change/test_uniq_vals_schema_change.out
new file mode 100644
index 0000000000..de0526b3e7
--- /dev/null
+++ b/regression-test/data/schema_change/test_uniq_vals_schema_change.out
@@ -0,0 +1,22 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sc --
+2
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 1
+
+-- !sc --
+3 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 2020-01-03T00:00 1 32 20 2
+
+-- !sc --
+3
+
+-- !sc --
+4 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 1 32 20 2
+
+-- !sc --
+5
+
+-- !sc --
+2 2017-10-01 Beijing 10 1 2020-01-03T00:00
2020-01-03T00:00 1 32 20 1
+
diff --git a/regression-test/data/schema_change/test_update_schema_change.out
b/regression-test/data/schema_change/test_update_schema_change.out
new file mode 100644
index 0000000000..aeacfd28c6
--- /dev/null
+++ b/regression-test/data/schema_change/test_update_schema_change.out
@@ -0,0 +1,64 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !test_update_schema_change --
+0
+
+-- !test_update_schema_change_2 --
+0
+
+-- !test_update_schema_change_3 --
+1
+
+-- !test_update_schema_change_4 --
+1
+
+-- !test_update_schema_change_5 --
+1 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20
+2 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21
+
+-- !test_update_schema_change_6 --
+0
+
+-- !test_update_schema_change_7 --
+2 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21 1
+1 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20 1
+
+-- !test_update_schema_change_8 --
+1
+
+-- !test_update_schema_change_9 --
+1 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20 2
+2 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21 1
+
+-- !test_update_schema_change_10 --
+1
+
+-- !test_update_schema_change_11 --
+1
+
+-- !test_update_schema_change_12 --
+2
+
+-- !test_update_schema_change_13 --
+5 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21 20
+3 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20 20
+2 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21 1
+1 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20 20
+
+-- !test_update_schema_change_14 --
+0
+
+-- !test_update_schema_change_15 --
+5 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21
+3 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20
+2 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21
+1 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20
+
+-- !test_update_schema_change_16 --
+1
+
+-- !test_update_schema_change_17 --
+5 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 20 31 21
+3 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20
+2 2017-10-01 Beijing 10 1 2020-01-02T00:00
2020-01-02T00:00 2020-01-02T00:00 1 31 21
+1 2017-10-01 Beijing 10 1 2020-01-01T00:00
2020-01-01T00:00 2020-01-01T00:00 1 30 20
+
diff --git
a/regression-test/suites/schema_change/test_agg_keys_schema_change.groovy
b/regression-test/suites/schema_change/test_agg_keys_schema_change.groovy
index 6e944e654c..72e6dd6292 100644
--- a/regression-test/suites/schema_change/test_agg_keys_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_agg_keys_schema_change.groovy
@@ -98,7 +98,7 @@ suite ("test_agg_keys_schema_change") {
result = "null"
while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = sql "SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
result = result.toString()
logger.info("result: ${result}")
if(result.contains("CANCELLED")){
@@ -128,7 +128,7 @@ suite ("test_agg_keys_schema_change") {
"""
result = "null"
while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = sql "SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
result = result.toString()
logger.info("result: ${result}")
if(result.contains("CANCELLED")){
diff --git
a/regression-test/suites/schema_change/test_agg_mv_schema_change.groovy
b/regression-test/suites/schema_change/test_agg_mv_schema_change.groovy
index 169f07240d..1bd0457207 100644
--- a/regression-test/suites/schema_change/test_agg_mv_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_agg_mv_schema_change.groovy
@@ -112,7 +112,7 @@ suite ("test_agg_mv_schema_change") {
result = "null"
while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = sql "SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
result = result.toString()
logger.info("result: ${result}")
if(result.contains("CANCELLED")) {
diff --git
a/regression-test/suites/schema_change/test_agg_rollup_schema_change.groovy
b/regression-test/suites/schema_change/test_agg_rollup_schema_change.groovy
index 850a4d02da..6dfe0743e8 100644
--- a/regression-test/suites/schema_change/test_agg_rollup_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_agg_rollup_schema_change.groovy
@@ -113,7 +113,7 @@ suite ("test_agg_rollup_schema_change") {
result = "null"
while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = sql "SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
result = result.toString()
logger.info("result: ${result}")
if(result.contains("CANCELLED")) {
diff --git
a/regression-test/suites/schema_change/test_alter_table_column.groovy
b/regression-test/suites/schema_change/test_alter_table_column.groovy
index 84b4dc2c28..333cbf5528 100644
--- a/regression-test/suites/schema_change/test_alter_table_column.groovy
+++ b/regression-test/suites/schema_change/test_alter_table_column.groovy
@@ -19,7 +19,7 @@ suite("test_alter_table_column", "schema_change") {
def tbName1 = "alter_table_column_dup"
def getJobState = { tableName ->
- def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
+ def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
return jobStateResult[0][9]
}
sql "DROP TABLE IF EXISTS ${tbName1}"
diff --git
a/regression-test/suites/schema_change/test_alter_table_column_with_delete.groovy
b/regression-test/suites/schema_change/test_alter_table_column_with_delete.groovy
index b26d82bfdf..8f034674af 100644
---
a/regression-test/suites/schema_change/test_alter_table_column_with_delete.groovy
+++
b/regression-test/suites/schema_change/test_alter_table_column_with_delete.groovy
@@ -18,7 +18,7 @@
suite("test_alter_table_column_with_delete", "schema_change") {
def tbName1 = "alter_table_column_dup_with_delete"
def getJobState = { tableName ->
- def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
+ def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
return jobStateResult[0][9]
}
sql "DROP TABLE IF EXISTS ${tbName1}"
diff --git
a/regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
b/regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
index e81be79de7..d8b7dd82d8 100644
--- a/regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
@@ -124,7 +124,7 @@ suite ("test_dup_keys_schema_change") {
"""
result = "null"
while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = sql "SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
result = result.toString()
logger.info("result: ${result}")
if(result.contains("CANCELLED")) {
diff --git
a/regression-test/suites/schema_change/test_dup_mv_schema_change.groovy
b/regression-test/suites/schema_change/test_dup_mv_schema_change.groovy
index 9318aaddd3..33401b0963 100644
--- a/regression-test/suites/schema_change/test_dup_mv_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_dup_mv_schema_change.groovy
@@ -138,7 +138,7 @@ suite ("test_dup_mv_schema_change") {
"""
result = "null"
while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = sql "SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
result = result.toString()
logger.info("result: ${result}")
if(result.contains("CANCELLED")) {
diff --git a/regression-test/suites/schema_change/test_schema_change.groovy
b/regression-test/suites/schema_change/test_schema_change.groovy
index 843e33f9b6..e68013da06 100644
--- a/regression-test/suites/schema_change/test_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_schema_change.groovy
@@ -20,7 +20,7 @@ suite("test_schema_change", "schema_change") {
def tbName = "alter_table_column_type"
def getJobState = { tableName ->
- def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
+ def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE
IndexName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
return jobStateResult[0][9]
}
diff --git
a/regression-test/suites/schema_change/test_uniq_keys_schema_change.groovy
b/regression-test/suites/schema_change/test_uniq_keys_schema_change.groovy
new file mode 100644
index 0000000000..a179542d45
--- /dev/null
+++ b/regression-test/suites/schema_change/test_uniq_keys_schema_change.groovy
@@ -0,0 +1,203 @@
+// 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_uniq_keys_schema_change") {
+ def tableName = "schema_change_uniq_keys_regression_test"
+
+ try {
+ String[][] backends = sql """ show backends; """
+ assertTrue(backends.size() > 0)
+ String backend_id;
+ def backendId_to_backendIP = [:]
+ def backendId_to_backendHttpPort = [:]
+ for (String[] backend in backends) {
+ backendId_to_backendIP.put(backend[0], backend[2])
+ backendId_to_backendHttpPort.put(backend[0], backend[5])
+ }
+
+ backend_id = backendId_to_backendIP.keySet()[0]
+ StringBuilder showConfigCommand = new StringBuilder();
+ showConfigCommand.append("curl -X GET http://")
+ showConfigCommand.append(backendId_to_backendIP.get(backend_id))
+ showConfigCommand.append(":")
+ showConfigCommand.append(backendId_to_backendHttpPort.get(backend_id))
+ showConfigCommand.append("/api/show_config")
+ logger.info(showConfigCommand.toString())
+ def process = showConfigCommand.toString().execute()
+ int code = process.waitFor()
+ String err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ String out = process.getText()
+ logger.info("Show config: code=" + code + ", out=" + out + ", err=" +
err)
+ assertEquals(code, 0)
+ def configList = parseJson(out.trim())
+ assert configList instanceof List
+
+ boolean disableAutoCompaction = true
+ for (Object ele in (List) configList) {
+ assert ele instanceof List<String>
+ if (((List<String>) ele)[0] == "disable_auto_compaction") {
+ disableAutoCompaction = Boolean.parseBoolean(((List<String>)
ele)[2])
+ }
+ }
+ sql """ DROP TABLE IF EXISTS ${tableName} """
+
+ sql """
+ CREATE TABLE schema_change_uniq_keys_regression_test (
+ `user_id` LARGEINT NOT NULL COMMENT "用户id",
+ `date` DATE NOT NULL COMMENT "数据灌入日期时间",
+ `city` VARCHAR(20) COMMENT "用户所在城市",
+ `age` SMALLINT COMMENT "用户年龄",
+ `sex` TINYINT COMMENT "用户性别",
+ `last_visit_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次访问时间",
+ `last_update_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次更新时间",
+ `last_visit_date_not_null` DATETIME NOT NULL DEFAULT
"1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
+ `cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
+ `max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
+ `min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间")
+ UNIQUE KEY(`user_id`, `date`, `city`, `age`, `sex`) DISTRIBUTED BY
HASH(`user_id`)
+ BUCKETS 1
+ PROPERTIES ( "replication_num" = "1", "light_schema_change" =
"true");
+ """
+
+ sql """ INSERT INTO schema_change_uniq_keys_regression_test VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-01', '2020-01-01',
'2020-01-01', 1, 30, 20)
+ """
+
+ sql """ INSERT INTO schema_change_uniq_keys_regression_test VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 19)
+ """
+
+ sql """ INSERT INTO schema_change_uniq_keys_regression_test VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 21)
+ """
+
+ sql """ INSERT INTO schema_change_uniq_keys_regression_test VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20)
+ """
+ qt_sc """
+ select count(*) from
schema_change_uniq_keys_regression_test
+ """
+
+ // add column
+ sql """
+ ALTER table ${tableName} ADD COLUMN new_column INT default "1"
+ """
+
+ sql """ SELECT * FROM ${tableName} WHERE user_id=2 """
+
+ sql """ INSERT INTO ${tableName}
(`user_id`,`date`,`city`,`age`,`sex`,`last_visit_date`,`last_update_date`,
+
`last_visit_date_not_null`,`cost`,`max_dwell_time`,`min_dwell_time`)
+ VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20)
+ """
+
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=3 """
+
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id = 3 """
+
+ qt_sc """ select count(*) from ${tableName} """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (4, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+
+ qt_sc """ select * from ${tableName} where user_id = 4 """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+
+ // compaction
+ String[][] tablets = sql """ show tablets from ${tableName}; """
+ for (String[] tablet in tablets) {
+ String tablet_id = tablet[0]
+ backend_id = tablet[2]
+ logger.info("run compaction:" + tablet_id)
+ StringBuilder sb = new StringBuilder();
+ sb.append("curl -X POST http://")
+ sb.append(backendId_to_backendIP.get(backend_id))
+ sb.append(":")
+ sb.append(backendId_to_backendHttpPort.get(backend_id))
+ sb.append("/api/compaction/run?tablet_id=")
+ sb.append(tablet_id)
+ sb.append("&compact_type=cumulative")
+
+ String command = sb.toString()
+ process = command.execute()
+ code = process.waitFor()
+ err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ out = process.getText()
+ logger.info("Run compaction: code=" + code + ", out=" + out + ",
err=" + err)
+ //assertEquals(code, 0)
+ }
+
+ // wait for all compactions done
+ for (String[] tablet in tablets) {
+ boolean running = true
+ do {
+ Thread.sleep(100)
+ String tablet_id = tablet[0]
+ backend_id = tablet[2]
+ StringBuilder sb = new StringBuilder();
+ sb.append("curl -X GET http://")
+ sb.append(backendId_to_backendIP.get(backend_id))
+ sb.append(":")
+ sb.append(backendId_to_backendHttpPort.get(backend_id))
+ sb.append("/api/compaction/run_status?tablet_id=")
+ sb.append(tablet_id)
+
+ String command = sb.toString()
+ process = command.execute()
+ code = process.waitFor()
+ err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ out = process.getText()
+ logger.info("Get compaction status: code=" + code + ", out=" +
out + ", err=" + err)
+ assertEquals(code, 0)
+ def compactionStatus = parseJson(out.trim())
+ assertEquals("success", compactionStatus.status.toLowerCase())
+ running = compactionStatus.run_status
+ } while (running)
+ }
+ qt_sc """ select count(*) from ${tableName} """
+
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=2 """
+
+ } finally {
+ //try_sql("DROP TABLE IF EXISTS ${tableName}")
+ }
+}
\ No newline at end of file
diff --git
a/regression-test/suites/schema_change/test_uniq_mv_schema_change.groovy
b/regression-test/suites/schema_change/test_uniq_mv_schema_change.groovy
new file mode 100644
index 0000000000..8695b4db98
--- /dev/null
+++ b/regression-test/suites/schema_change/test_uniq_mv_schema_change.groovy
@@ -0,0 +1,226 @@
+// 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_uniq_mv_schema_change") {
+ def tableName = "schema_change_uniq_mv_regression_test"
+
+ try {
+ String[][] backends = sql """ show backends; """
+ assertTrue(backends.size() > 0)
+ String backend_id;
+ def backendId_to_backendIP = [:]
+ def backendId_to_backendHttpPort = [:]
+ for (String[] backend in backends) {
+ backendId_to_backendIP.put(backend[0], backend[2])
+ backendId_to_backendHttpPort.put(backend[0], backend[5])
+ }
+
+ backend_id = backendId_to_backendIP.keySet()[0]
+ StringBuilder showConfigCommand = new StringBuilder();
+ showConfigCommand.append("curl -X GET http://")
+ showConfigCommand.append(backendId_to_backendIP.get(backend_id))
+ showConfigCommand.append(":")
+ showConfigCommand.append(backendId_to_backendHttpPort.get(backend_id))
+ showConfigCommand.append("/api/show_config")
+ logger.info(showConfigCommand.toString())
+ def process = showConfigCommand.toString().execute()
+ int code = process.waitFor()
+ String err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ String out = process.getText()
+ logger.info("Show config: code=" + code + ", out=" + out + ", err=" +
err)
+ assertEquals(code, 0)
+ def configList = parseJson(out.trim())
+ assert configList instanceof List
+
+ boolean disableAutoCompaction = true
+ for (Object ele in (List) configList) {
+ assert ele instanceof List<String>
+ if (((List<String>) ele)[0] == "disable_auto_compaction") {
+ disableAutoCompaction = Boolean.parseBoolean(((List<String>)
ele)[2])
+ }
+ }
+ sql """ DROP TABLE IF EXISTS ${tableName} """
+
+ sql """
+ CREATE TABLE ${tableName} (
+ `user_id` LARGEINT NOT NULL COMMENT "用户id",
+ `date` DATE NOT NULL COMMENT "数据灌入日期时间",
+ `city` VARCHAR(20) COMMENT "用户所在城市",
+ `age` SMALLINT COMMENT "用户年龄",
+ `sex` TINYINT COMMENT "用户性别",
+ `last_visit_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次访问时间",
+ `last_update_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次更新时间",
+ `last_visit_date_not_null` DATETIME NOT NULL DEFAULT
"1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
+ `cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
+ `max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
+ `min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间")
+ UNIQUE KEY(`user_id`, `date`, `city`, `age`, `sex`) DISTRIBUTED BY
HASH(`user_id`)
+ BUCKETS 1
+ PROPERTIES ( "replication_num" = "1", "light_schema_change" =
"true");
+ """
+
+ //add materialized view
+ def result = "null"
+ def mvName = "mv1"
+ sql "create materialized view ${mvName} as select user_id, date, city,
age, sex from ${tableName} group by user_id, date, city, age, sex;"
+ while (!result.contains("FINISHED")){
+ result = sql "SHOW ALTER TABLE MATERIALIZED VIEW WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
+ result = result.toString()
+ logger.info("result: ${result}")
+ if(result.contains("CANCELLED")){
+ return
+ }
+ Thread.sleep(100)
+ }
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-01', '2020-01-01',
'2020-01-01', 1, 30, 20)
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 19)
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 21)
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20)
+ """
+ qt_sc """
+ select count(*) from ${tableName}
+ """
+
+ // add column
+ sql """
+ ALTER table ${tableName} ADD COLUMN new_column INT default "1"
+ """
+
+ sql """ SELECT * FROM ${tableName} WHERE user_id=2 """
+
+ sql """ INSERT INTO ${tableName}
(`user_id`,`date`,`city`,`age`,`sex`,`last_visit_date`,`last_update_date`,
+
`last_visit_date_not_null`,`cost`,`max_dwell_time`,`min_dwell_time`)
+ VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20)
+ """
+
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=3 """
+
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id = 3 """
+
+ qt_sc """ select count(*) from ${tableName} """
+
+
+ // drop column
+ sql """
+ ALTER TABLE ${tableName} DROP COLUMN cost
+ """
+
+ qt_sc """ select * from ${tableName} where user_id = 3 """
+
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (4, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+
+ qt_sc """ select * from ${tableName} where user_id = 4 """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+
+ // compaction
+ String[][] tablets = sql """ show tablets from ${tableName}; """
+ for (String[] tablet in tablets) {
+ String tablet_id = tablet[0]
+ backend_id = tablet[2]
+ logger.info("run compaction:" + tablet_id)
+ StringBuilder sb = new StringBuilder();
+ sb.append("curl -X POST http://")
+ sb.append(backendId_to_backendIP.get(backend_id))
+ sb.append(":")
+ sb.append(backendId_to_backendHttpPort.get(backend_id))
+ sb.append("/api/compaction/run?tablet_id=")
+ sb.append(tablet_id)
+ sb.append("&compact_type=cumulative")
+
+ String command = sb.toString()
+ process = command.execute()
+ code = process.waitFor()
+ err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ out = process.getText()
+ logger.info("Run compaction: code=" + code + ", out=" + out + ",
err=" + err)
+ //assertEquals(code, 0)
+ }
+
+ // wait for all compactions done
+ for (String[] tablet in tablets) {
+ boolean running = true
+ do {
+ Thread.sleep(100)
+ String tablet_id = tablet[0]
+ backend_id = tablet[2]
+ StringBuilder sb = new StringBuilder();
+ sb.append("curl -X GET http://")
+ sb.append(backendId_to_backendIP.get(backend_id))
+ sb.append(":")
+ sb.append(backendId_to_backendHttpPort.get(backend_id))
+ sb.append("/api/compaction/run_status?tablet_id=")
+ sb.append(tablet_id)
+
+ String command = sb.toString()
+ process = command.execute()
+ code = process.waitFor()
+ err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ out = process.getText()
+ logger.info("Get compaction status: code=" + code + ", out=" +
out + ", err=" + err)
+ assertEquals(code, 0)
+ def compactionStatus = parseJson(out.trim())
+ assertEquals("success", compactionStatus.status.toLowerCase())
+ running = compactionStatus.run_status
+ } while (running)
+ }
+ qt_sc """ select count(*) from ${tableName} """
+
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=2 """
+
+ } finally {
+ //try_sql("DROP TABLE IF EXISTS ${tableName}")
+ }
+}
\ No newline at end of file
diff --git
a/regression-test/suites/schema_change/test_uniq_rollup_schema_change.groovy
b/regression-test/suites/schema_change/test_uniq_rollup_schema_change.groovy
new file mode 100644
index 0000000000..d0b2cf64e1
--- /dev/null
+++ b/regression-test/suites/schema_change/test_uniq_rollup_schema_change.groovy
@@ -0,0 +1,237 @@
+// 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_uniq_rollup_schema_change") {
+ def tableName = "schema_change_uniq_rollup_regression_test"
+
+ try {
+ String[][] backends = sql """ show backends; """
+ assertTrue(backends.size() > 0)
+ String backend_id;
+ def backendId_to_backendIP = [:]
+ def backendId_to_backendHttpPort = [:]
+ for (String[] backend in backends) {
+ backendId_to_backendIP.put(backend[0], backend[2])
+ backendId_to_backendHttpPort.put(backend[0], backend[5])
+ }
+
+ backend_id = backendId_to_backendIP.keySet()[0]
+ StringBuilder showConfigCommand = new StringBuilder();
+ showConfigCommand.append("curl -X GET http://")
+ showConfigCommand.append(backendId_to_backendIP.get(backend_id))
+ showConfigCommand.append(":")
+ showConfigCommand.append(backendId_to_backendHttpPort.get(backend_id))
+ showConfigCommand.append("/api/show_config")
+ logger.info(showConfigCommand.toString())
+ def process = showConfigCommand.toString().execute()
+ int code = process.waitFor()
+ String err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ String out = process.getText()
+ logger.info("Show config: code=" + code + ", out=" + out + ", err=" +
err)
+ assertEquals(code, 0)
+ def configList = parseJson(out.trim())
+ assert configList instanceof List
+
+ boolean disableAutoCompaction = true
+ for (Object ele in (List) configList) {
+ assert ele instanceof List<String>
+ if (((List<String>) ele)[0] == "disable_auto_compaction") {
+ disableAutoCompaction = Boolean.parseBoolean(((List<String>)
ele)[2])
+ }
+ }
+ sql """ DROP TABLE IF EXISTS ${tableName} """
+
+ sql """
+ CREATE TABLE ${tableName} (
+ `user_id` LARGEINT NOT NULL COMMENT "用户id",
+ `date` DATE NOT NULL COMMENT "数据灌入日期时间",
+ `city` VARCHAR(20) COMMENT "用户所在城市",
+ `age` SMALLINT COMMENT "用户年龄",
+ `sex` TINYINT COMMENT "用户性别",
+ `last_visit_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次访问时间",
+ `last_update_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次更新时间",
+ `last_visit_date_not_null` DATETIME NOT NULL DEFAULT
"1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
+ `cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
+ `max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
+ `min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间")
+ UNIQUE KEY(`user_id`, `date`, `city`, `age`, `sex`) DISTRIBUTED BY
HASH(`user_id`)
+ BUCKETS 1
+ PROPERTIES ( "replication_num" = "1", "light_schema_change" =
"true" );
+ """
+
+ //add rollup
+ def result = "null"
+ def rollupName = "rollup_cost"
+ sql "ALTER TABLE ${tableName} ADD ROLLUP
${rollupName}(`user_id`,`date`,`city`,`age`,`sex`, cost);"
+ while (!result.contains("FINISHED")){
+ result = sql "SHOW ALTER TABLE ROLLUP WHERE TableName='${tableName}'
ORDER BY CreateTime DESC LIMIT 1;"
+ result = result.toString()
+ logger.info("result: ${result}")
+ if(result.contains("CANCELLED")){
+ return
+ }
+ Thread.sleep(100)
+ }
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-01', '2020-01-01',
'2020-01-01', 1, 30, 20)
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 19)
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 21)
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20)
+ """
+ qt_sc """
+ select count(*) from ${tableName}
+ """
+
+ // add column
+ sql """
+ ALTER table ${tableName} ADD COLUMN new_column INT default "1"
+ """
+
+ sql """ SELECT * FROM ${tableName} WHERE user_id=2 """
+
+ sql """ INSERT INTO ${tableName}
(`user_id`,`date`,`city`,`age`,`sex`,`last_visit_date`,`last_update_date`,
+
`last_visit_date_not_null`,`cost`,`max_dwell_time`,`min_dwell_time`)
+ VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20)
+ """
+
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=3 """
+
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ """
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id = 3 """
+
+
+ qt_sc """ select count(*) from ${tableName} """
+
+ // drop column
+ sql """
+ ALTER TABLE ${tableName} DROP COLUMN cost
+ """
+
+ result = "null"
+ while (!result.contains("FINISHED")){
+ result = sql "SHOW ALTER TABLE COLUMN WHERE IndexName='${tableName}'
ORDER BY CreateTime DESC LIMIT 1;"
+ result = result.toString()
+ logger.info("result: ${result}")
+ if(result.contains("CANCELLED")) {
+ log.info("rollup job is cancelled, result: ${result}".toString())
+ return
+ }
+ Thread.sleep(100)
+ }
+
+ qt_sc """ select * from ${tableName} where user_id = 3 """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (4, '2017-10-01', 'Beijing', 10, 1,'2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+
+ qt_sc """ select * from ${tableName} where user_id = 4 """
+
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1,'2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+ sql """ INSERT INTO ${tableName} VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03', '2020-01-03',
'2020-01-03', 32, 20, 2)
+ """
+
+ // compaction
+ String[][] tablets = sql """ show tablets from ${tableName}; """
+ for (String[] tablet in tablets) {
+ String tablet_id = tablet[0]
+ backend_id = tablet[2]
+ logger.info("run compaction:" + tablet_id)
+ StringBuilder sb = new StringBuilder();
+ sb.append("curl -X POST http://")
+ sb.append(backendId_to_backendIP.get(backend_id))
+ sb.append(":")
+ sb.append(backendId_to_backendHttpPort.get(backend_id))
+ sb.append("/api/compaction/run?tablet_id=")
+ sb.append(tablet_id)
+ sb.append("&compact_type=cumulative")
+
+ String command = sb.toString()
+ process = command.execute()
+ code = process.waitFor()
+ err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ out = process.getText()
+ logger.info("Run compaction: code=" + code + ", out=" + out + ",
err=" + err)
+ //assertEquals(code, 0)
+ }
+
+ // wait for all compactions done
+ for (String[] tablet in tablets) {
+ boolean running = true
+ do {
+ Thread.sleep(100)
+ String tablet_id = tablet[0]
+ backend_id = tablet[2]
+ StringBuilder sb = new StringBuilder();
+ sb.append("curl -X GET http://")
+ sb.append(backendId_to_backendIP.get(backend_id))
+ sb.append(":")
+ sb.append(backendId_to_backendHttpPort.get(backend_id))
+ sb.append("/api/compaction/run_status?tablet_id=")
+ sb.append(tablet_id)
+
+ String command = sb.toString()
+ process = command.execute()
+ code = process.waitFor()
+ err = IOGroovyMethods.getText(new BufferedReader(new
InputStreamReader(process.getErrorStream())));
+ out = process.getText()
+ logger.info("Get compaction status: code=" + code + ", out=" +
out + ", err=" + err)
+ assertEquals(code, 0)
+ def compactionStatus = parseJson(out.trim())
+ assertEquals("success", compactionStatus.status.toLowerCase())
+ running = compactionStatus.run_status
+ } while (running)
+ }
+ qt_sc """ select count(*) from ${tableName} """
+
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=2 """
+
+ } finally {
+ //try_sql("DROP TABLE IF EXISTS ${tableName}")
+ }
+}
\ No newline at end of file
diff --git
a/regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
b/regression-test/suites/schema_change/test_uniq_vals_schema_change.groovy
similarity index 82%
copy from
regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
copy to regression-test/suites/schema_change/test_uniq_vals_schema_change.groovy
index e81be79de7..1cea755bee 100644
--- a/regression-test/suites/schema_change/test_dup_keys_schema_change.groovy
+++ b/regression-test/suites/schema_change/test_uniq_vals_schema_change.groovy
@@ -17,8 +17,8 @@
import org.codehaus.groovy.runtime.IOGroovyMethods
-suite ("test_dup_keys_schema_change") {
- def tableName = "schema_change_dup_keys_regression_test"
+suite ("test_uniq_vals_schema_change") {
+ def tableName = "schema_change_uniq_vals_regression_test"
try {
String[][] backends = sql """ show backends; """
@@ -55,7 +55,6 @@ suite ("test_dup_keys_schema_change") {
disableAutoCompaction = Boolean.parseBoolean(((List<String>)
ele)[2])
}
}
-
sql """ DROP TABLE IF EXISTS ${tableName} """
sql """
@@ -71,7 +70,7 @@ suite ("test_dup_keys_schema_change") {
`cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
`max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
`min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间")
- DUPLICATE KEY(`user_id`, `date`, `city`, `age`, `sex`)
DISTRIBUTED BY HASH(`user_id`)
+ UNIQUE KEY(`user_id`, `date`, `city`, `age`, `sex`)
DISTRIBUTED BY HASH(`user_id`)
BUCKETS 1
PROPERTIES ( "replication_num" = "1", "light_schema_change" =
"true" );
"""
@@ -91,7 +90,8 @@ suite ("test_dup_keys_schema_change") {
sql """ INSERT INTO ${tableName} VALUES
(2, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', '2020-01-03', 1, 32, 20)
"""
- qt_sc """
+
+ qt_sc"""
select count(*) from ${tableName}
"""
@@ -100,7 +100,7 @@ suite ("test_dup_keys_schema_change") {
ALTER table ${tableName} ADD COLUMN new_column INT default "1"
"""
- sql """ SELECT * FROM ${tableName} WHERE user_id=2 order by
min_dwell_time """
+ sql """ SELECT * FROM ${tableName} WHERE user_id=2 """
sql """ INSERT INTO ${tableName}
(`user_id`,`date`,`city`,`age`,`sex`,`last_visit_date`,`last_update_date`,
`last_visit_date_not_null`,`cost`,`max_dwell_time`,`min_dwell_time`)
@@ -114,52 +114,40 @@ suite ("test_dup_keys_schema_change") {
sql """ INSERT INTO ${tableName} VALUES
(3, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', '2020-01-03', 1, 32, 20, 2)
"""
- qt_sc """ SELECT * FROM ${tableName} WHERE user_id = 3 order by
new_column """
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id = 3 """
qt_sc """ select count(*) from ${tableName} """
// drop column
sql """
- ALTER TABLE ${tableName} DROP COLUMN sex
- """
- result = "null"
- while (!result.contains("FINISHED")){
- result = sql "SHOW ALTER TABLE COLUMN WHERE
TableName='${tableName}' ORDER BY CreateTime DESC LIMIT 1;"
- result = result.toString()
- logger.info("result: ${result}")
- if(result.contains("CANCELLED")) {
- log.info("rollup job is cancelled, result:
${result}".toString())
- return
- }
- Thread.sleep(100)
- }
- qt_sc """ select * from ${tableName} where user_id = 3 order by
new_column """
-
+ ALTER TABLE ${tableName} DROP COLUMN last_visit_date
+ """
+ qt_sc = sql """ select * from ${tableName} where user_id = 3 """
sql """ INSERT INTO ${tableName} VALUES
- (4, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (4, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
qt_sc """ select * from ${tableName} where user_id = 4 """
sql """ INSERT INTO ${tableName} VALUES
- (5, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
sql """ INSERT INTO ${tableName} VALUES
- (5, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
sql """ INSERT INTO ${tableName} VALUES
- (5, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
sql """ INSERT INTO ${tableName} VALUES
- (5, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
sql """ INSERT INTO ${tableName} VALUES
- (5, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
sql """ INSERT INTO ${tableName} VALUES
- (5, '2017-10-01', 'Beijing', 10, '2020-01-03', '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-03',
'2020-01-03', 1, 32, 20, 2)
"""
// compaction
@@ -213,13 +201,12 @@ suite ("test_dup_keys_schema_change") {
running = compactionStatus.run_status
} while (running)
}
-
qt_sc """ select count(*) from ${tableName} """
- qt_sc """ SELECT * FROM ${tableName} WHERE user_id=2 order by
min_dwell_time"""
+ qt_sc """ SELECT * FROM ${tableName} WHERE user_id=2 """
} finally {
//try_sql("DROP TABLE IF EXISTS ${tableName}")
}
-}
+}
\ No newline at end of file
diff --git a/regression-test/suites/schema_change/test_update_schema_change.sql
b/regression-test/suites/schema_change/test_update_schema_change.sql
new file mode 100644
index 0000000000..bf0241a02b
--- /dev/null
+++ b/regression-test/suites/schema_change/test_update_schema_change.sql
@@ -0,0 +1,50 @@
+DROP TABLE IF EXISTS schema_change_update_regression_test;
+
+CREATE TABLE schema_change_update_regression_test (
+ `user_id` LARGEINT NOT NULL COMMENT "用户id",
+ `date` DATE NOT NULL COMMENT "数据灌入日期时间",
+ `city` VARCHAR(20) COMMENT "用户所在城市",
+ `age` SMALLINT COMMENT "用户年龄",
+ `sex` TINYINT COMMENT "用户性别",
+ `last_visit_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次访问时间",
+ `last_update_date` DATETIME DEFAULT "1970-01-01 00:00:00"
COMMENT "用户最后一次更新时间",
+ `last_visit_date_not_null` DATETIME NOT NULL DEFAULT
"1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
+ `cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
+ `max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
+ `min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间")
+ UNIQUE KEY(`user_id`, `date`, `city`, `age`, `sex`) DISTRIBUTED BY
HASH(`user_id`)
+ PROPERTIES ( "replication_num" = "1" , "light_schema_change" =
"true");
+
+INSERT INTO schema_change_update_regression_test VALUES
+ (1, '2017-10-01', 'Beijing', 10, 1, '2020-01-01', '2020-01-01',
'2020-01-01', 1, 30, 20);
+
+INSERT INTO schema_change_update_regression_test VALUES
+ (2, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 21);
+
+SELECT * FROM schema_change_update_regression_test order by user_id ASC,
last_visit_date;
+
+ALTER table schema_change_update_regression_test ADD COLUMN new_column INT
default "1";
+
+SELECT * FROM schema_change_update_regression_test order by user_id DESC,
last_visit_date;
+
+UPDATE schema_change_update_regression_test set new_column = 2 where user_id =
1;
+
+SELECT * FROM schema_change_update_regression_test order by user_id ASC,
last_visit_date;
+
+INSERT INTO schema_change_update_regression_test VALUES
+ (3, '2017-10-01', 'Beijing', 10, 1, '2020-01-01', '2020-01-01',
'2020-01-01', 1, 30, 20, 2);
+
+INSERT INTO schema_change_update_regression_test VALUES
+ (5, '2017-10-01', 'Beijing', 10, 1, '2020-01-02', '2020-01-02',
'2020-01-02', 1, 31, 21, 20);
+
+UPDATE schema_change_update_regression_test set new_column = 20 where
new_column = 2;
+
+SELECT * FROM schema_change_update_regression_test order by user_id DESC,
last_visit_date;
+
+ALTER TABLE schema_change_update_regression_test DROP COLUMN new_column;
+
+SELECT * FROM schema_change_update_regression_test order by user_id DESC,
last_visit_date;
+
+UPDATE schema_change_update_regression_test set cost = 20 where user_id = 5;
+
+SELECT * FROM schema_change_update_regression_test order by user_id DESC,
last_visit_date;
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]