You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by kx...@apache.org on 2023/06/09 04:10:45 UTC

[doris] 09/29: [Bug](row-store) Fix row store with materialize index (#20356)

This is an automated email from the ASF dual-hosted git repository.

kxiao pushed a commit to branch branch-2.0-beta
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 166fc4f134ced589c58a0582eb8ed0e9991d834b
Author: lihangyu <15...@163.com>
AuthorDate: Thu Jun 8 10:55:22 2023 +0800

    [Bug](row-store) Fix row store with materialize index (#20356)
    
    If a query hits a materialized view that has row storage enabled, but the row storage column is not present in the materialized view, it will result in a query crash. Therefore, it is necessary to include the row storage column when creating the materialized view, and serialize the row storage column during the execution of SchemaChange.
---
 be/src/olap/compaction.cpp                         |   1 +
 be/src/olap/delta_writer.cpp                       |   2 +-
 be/src/olap/olap_define.h                          |   7 ++
 be/src/olap/rowset/beta_rowset_writer.cpp          |   4 +-
 be/src/olap/rowset/rowset_writer_context.h         |   5 +-
 be/src/olap/rowset/segment_v2/segment_writer.cpp   |  13 ++-
 be/src/olap/rowset/segment_v2/segment_writer.h     |   4 +-
 be/src/olap/schema_change.cpp                      |   2 +
 be/src/olap/txn_manager.cpp                        |   2 +-
 .../doris/alter/MaterializedViewHandler.java       |   5 +
 .../main/java/org/apache/doris/catalog/Column.java |   3 +-
 .../java/org/apache/doris/catalog/OlapTable.java   |   9 ++
 .../org/apache/doris/task/AlterReplicaTask.java    |   1 -
 regression-test/data/point_query_p0/load.out       |  25 +++++
 regression-test/suites/point_query_p0/load.groovy  | 101 +++++++++++++++++++++
 15 files changed, 168 insertions(+), 16 deletions(-)

diff --git a/be/src/olap/compaction.cpp b/be/src/olap/compaction.cpp
index 0b1a702654..8b1e0e98b1 100644
--- a/be/src/olap/compaction.cpp
+++ b/be/src/olap/compaction.cpp
@@ -457,6 +457,7 @@ Status Compaction::construct_output_rowset_writer(RowsetWriterContext& ctx, bool
     ctx.segments_overlap = NONOVERLAPPING;
     ctx.tablet_schema = _cur_tablet_schema;
     ctx.newest_write_timestamp = _newest_write_timestamp;
+    ctx.write_type = DataWriteType::TYPE_COMPACTION;
     if (config::inverted_index_compaction_enable &&
         ((_tablet->keys_type() == KeysType::UNIQUE_KEYS ||
           _tablet->keys_type() == KeysType::DUP_KEYS))) {
diff --git a/be/src/olap/delta_writer.cpp b/be/src/olap/delta_writer.cpp
index d60c88b807..4122e957e0 100644
--- a/be/src/olap/delta_writer.cpp
+++ b/be/src/olap/delta_writer.cpp
@@ -200,7 +200,7 @@ Status DeltaWriter::init() {
     context.newest_write_timestamp = UnixSeconds();
     context.tablet_id = _tablet->table_id();
     context.tablet = _tablet;
-    context.is_direct_write = true;
+    context.write_type = DataWriteType::TYPE_DIRECT;
     context.mow_context =
             std::make_shared<MowContext>(_cur_max_version, _rowset_ids, _delete_bitmap);
     RETURN_IF_ERROR(_tablet->create_rowset_writer(context, &_rowset_writer));
diff --git a/be/src/olap/olap_define.h b/be/src/olap/olap_define.h
index 42f8dfe83b..ff896e0ff8 100644
--- a/be/src/olap/olap_define.h
+++ b/be/src/olap/olap_define.h
@@ -131,6 +131,13 @@ enum ColumnFamilyIndex {
     META_COLUMN_FAMILY_INDEX,
 };
 
+enum class DataWriteType {
+    TYPE_DEFAULT = 0,
+    TYPE_DIRECT,
+    TYPE_SCHEMA_CHANGE,
+    TYPE_COMPACTION,
+};
+
 static const char* const HINIS_KEY_SEPARATOR = ";";
 static const char* const HINIS_KEY_PAIR_SEPARATOR = "|";
 static const char* const HINIS_KEY_GROUP_SEPARATOR = "&";
diff --git a/be/src/olap/rowset/beta_rowset_writer.cpp b/be/src/olap/rowset/beta_rowset_writer.cpp
index c729a65077..4e462f1e4b 100644
--- a/be/src/olap/rowset/beta_rowset_writer.cpp
+++ b/be/src/olap/rowset/beta_rowset_writer.cpp
@@ -721,9 +721,9 @@ Status BetaRowsetWriter::_do_create_segment_writer(
     segment_v2::SegmentWriterOptions writer_options;
     writer_options.enable_unique_key_merge_on_write = _context.enable_unique_key_merge_on_write;
     writer_options.rowset_ctx = &_context;
-    writer_options.is_direct_write = _context.is_direct_write;
+    writer_options.write_type = _context.write_type;
     if (is_segcompaction) {
-        writer_options.is_direct_write = false;
+        writer_options.write_type = DataWriteType::TYPE_COMPACTION;
     }
 
     if (is_segcompaction) {
diff --git a/be/src/olap/rowset/rowset_writer_context.h b/be/src/olap/rowset/rowset_writer_context.h
index e526f80158..904966d8e3 100644
--- a/be/src/olap/rowset/rowset_writer_context.h
+++ b/be/src/olap/rowset/rowset_writer_context.h
@@ -20,6 +20,7 @@
 #include <gen_cpp/olap_file.pb.h>
 
 #include "io/fs/file_system.h"
+#include "olap/olap_define.h"
 #include "olap/tablet.h"
 #include "olap/tablet_schema.h"
 
@@ -82,9 +83,7 @@ struct RowsetWriterContext {
     int64_t newest_write_timestamp;
     bool enable_unique_key_merge_on_write = false;
     std::set<int32_t> skip_inverted_index;
-    // If it is directly write from load procedure, else
-    // it could be compaction or schema change etc..
-    bool is_direct_write = false;
+    DataWriteType write_type = DataWriteType::TYPE_DEFAULT;
     std::shared_ptr<Tablet> tablet = nullptr;
     // for tracing local schema change record
     std::shared_ptr<vectorized::schema_util::LocalSchemaChangeRecorder> schema_change_recorder =
diff --git a/be/src/olap/rowset/segment_v2/segment_writer.cpp b/be/src/olap/rowset/segment_v2/segment_writer.cpp
index 594e951d33..3eaaf325c4 100644
--- a/be/src/olap/rowset/segment_v2/segment_writer.cpp
+++ b/be/src/olap/rowset/segment_v2/segment_writer.cpp
@@ -167,7 +167,8 @@ Status SegmentWriter::init(const std::vector<uint32_t>& col_ids, bool has_key,
                     _opts.rowset_ctx->skip_inverted_index.count(column.unique_id()) > 0;
         }
         // skip write inverted index on load if skip_write_index_on_load is true
-        if (_opts.is_direct_write && _tablet_schema->skip_write_index_on_load()) {
+        if (_opts.write_type == DataWriteType::TYPE_DIRECT &&
+            _tablet_schema->skip_write_index_on_load()) {
             skip_inverted_index = true;
         }
         // indexes for this column
@@ -279,7 +280,7 @@ void SegmentWriter::_maybe_invalid_row_cache(const std::string& key) {
     // If we update/insert cache, if load failed rowset will not be visible but cached data
     // will be visible, and lead to inconsistency.
     if (!config::disable_storage_row_cache && _tablet_schema->store_row_column() &&
-        _opts.is_direct_write) {
+        _opts.write_type == DataWriteType::TYPE_DIRECT) {
         // invalidate cache
         RowCache::instance()->erase({_opts.rowset_ctx->tablet_id, key});
     }
@@ -502,14 +503,18 @@ Status SegmentWriter::fill_missing_columns(vectorized::MutableColumns& mutable_f
 
 Status SegmentWriter::append_block(const vectorized::Block* block, size_t row_pos,
                                    size_t num_rows) {
-    if (_tablet_schema->is_partial_update() && _opts.is_direct_write) {
+    if (_tablet_schema->is_partial_update() && _opts.write_type == DataWriteType::TYPE_DIRECT) {
         RETURN_IF_ERROR(append_block_with_partial_content(block, row_pos, num_rows));
         return Status::OK();
     }
     CHECK(block->columns() >= _column_writers.size())
             << ", block->columns()=" << block->columns()
             << ", _column_writers.size()=" << _column_writers.size();
-    if (_tablet_schema->store_row_column() && _opts.is_direct_write) {
+    // Row column should be filled here when it's a directly write from memtable
+    // or it's schema change write(since column data type maybe changed, so we should reubild)
+    if (_tablet_schema->store_row_column() &&
+        (_opts.write_type == DataWriteType::TYPE_DIRECT ||
+         _opts.write_type == DataWriteType::TYPE_SCHEMA_CHANGE)) {
         _serialize_block_to_row_column(*const_cast<vectorized::Block*>(block));
     }
 
diff --git a/be/src/olap/rowset/segment_v2/segment_writer.h b/be/src/olap/rowset/segment_v2/segment_writer.h
index 09a3576cf5..837827b70a 100644
--- a/be/src/olap/rowset/segment_v2/segment_writer.h
+++ b/be/src/olap/rowset/segment_v2/segment_writer.h
@@ -72,12 +72,10 @@ extern const uint32_t k_segment_magic_length;
 struct SegmentWriterOptions {
     uint32_t num_rows_per_block = 1024;
     bool enable_unique_key_merge_on_write = false;
-    bool is_direct_write = false;
     CompressionTypePB compression_type = UNKNOWN_COMPRESSION;
 
     RowsetWriterContext* rowset_ctx = nullptr;
-    // If it is directly write from load procedure, else
-    // it could be compaction or schema change etc..
+    DataWriteType write_type = DataWriteType::TYPE_DEFAULT;
 };
 
 using TabletSharedPtr = std::shared_ptr<Tablet>;
diff --git a/be/src/olap/schema_change.cpp b/be/src/olap/schema_change.cpp
index 48fbe5bca1..75ce050f10 100644
--- a/be/src/olap/schema_change.cpp
+++ b/be/src/olap/schema_change.cpp
@@ -597,6 +597,7 @@ Status VSchemaChangeWithSorting::_internal_sorting(
     context.segments_overlap = segments_overlap;
     context.tablet_schema = new_tablet->tablet_schema();
     context.newest_write_timestamp = newest_write_timestamp;
+    context.write_type = DataWriteType::TYPE_SCHEMA_CHANGE;
     RETURN_IF_ERROR(new_tablet->create_rowset_writer(context, &rowset_writer));
 
     Defer defer {[&]() {
@@ -1103,6 +1104,7 @@ Status SchemaChangeHandler::_convert_historical_rowsets(const SchemaChangeParams
         context.tablet_schema = new_tablet->tablet_schema();
         context.newest_write_timestamp = rs_reader->newest_write_timestamp();
         context.fs = rs_reader->rowset()->rowset_meta()->fs();
+        context.write_type = DataWriteType::TYPE_SCHEMA_CHANGE;
         Status status = new_tablet->create_rowset_writer(context, &rowset_writer);
         if (!status.ok()) {
             res = Status::Error<ROWSET_BUILDER_INIT>();
diff --git a/be/src/olap/txn_manager.cpp b/be/src/olap/txn_manager.cpp
index 37fc94bd23..4119dced46 100644
--- a/be/src/olap/txn_manager.cpp
+++ b/be/src/olap/txn_manager.cpp
@@ -443,7 +443,7 @@ Status TxnManager::_create_transient_rowset_writer(std::shared_ptr<Tablet> table
     context.newest_write_timestamp = UnixSeconds();
     context.tablet_id = tablet->table_id();
     context.tablet = tablet;
-    context.is_direct_write = true;
+    context.write_type = DataWriteType::TYPE_DIRECT;
     RETURN_IF_ERROR(tablet->create_transient_rowset_writer(context, rowset_ptr->rowset_id(),
                                                            rowset_writer));
     (*rowset_writer)->set_segment_start_id(rowset_ptr->num_segments());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java b/fe/fe-core/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
index d9c2e5469e..e54c18a357 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
@@ -572,6 +572,11 @@ public class MaterializedViewHandler extends AlterHandler {
             newColumn.setAggregationType(AggregateType.REPLACE, true);
             newMVColumns.add(newColumn);
         }
+        if (olapTable.storeRowColumn()) {
+            Column newColumn = new Column(olapTable.getRowStoreCol());
+            newColumn.setAggregationType(AggregateType.NONE, true);
+            newMVColumns.add(newColumn);
+        }
         // if the column is complex type, we forbid to create materialized view
         for (Column column : newMVColumns) {
             if (column.getDataType().isComplexType() || column.getDataType().isJsonbType()) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
index 936db90a35..ff54f27026 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
@@ -356,7 +356,8 @@ public class Column implements Writable, GsonPostProcessable {
 
     public boolean isRowStoreColumn() {
         return !visible && (aggregationType == AggregateType.REPLACE
-                || aggregationType == AggregateType.NONE) && nameEquals(ROW_STORE_COL, true);
+                || aggregationType == AggregateType.NONE || aggregationType == null)
+                && nameEquals(ROW_STORE_COL, true);
     }
 
     public boolean isVersionColumn() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
index 50e36866ba..91910331e8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
@@ -1019,6 +1019,15 @@ public class OlapTable extends Table {
         return null;
     }
 
+    public Column getRowStoreCol() {
+        for (Column column : getBaseSchema(true)) {
+            if (column.isRowStoreColumn()) {
+                return column;
+            }
+        }
+        return null;
+    }
+
     public Boolean hasSequenceCol() {
         return getSequenceCol() != null;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java b/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java
index 9bdf4986fc..178550dd22 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java
@@ -42,7 +42,6 @@ import java.util.Map;
  * The new replica can be a rollup replica, or a shadow replica of schema change.
  */
 public class AlterReplicaTask extends AgentTask {
-
     private long baseTabletId;
     private long newReplicaId;
     private int baseSchemaHash;
diff --git a/regression-test/data/point_query_p0/load.out b/regression-test/data/point_query_p0/load.out
new file mode 100644
index 0000000000..ef2d9c2702
--- /dev/null
+++ b/regression-test/data/point_query_p0/load.out
@@ -0,0 +1,25 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !sql --
+-2147475406	true	45	23794	-11023	915989078	2115356192	15927.068	1.392557423391501E9	45951348783208518.810	8340516346665031.310	2022-01-26	2022-04-13T11:13:48	2022-01-31	2022-02-16T06:07:21	130.50.6.0	DeniseMatthews@Yozio.mil	Londonderry Alley 61
+-2147424303	false	-28	-5177	-1409	149417728	553396597	-10123.558	-1.268722910924068E9	67354830622005524.848	52407243294991364.348	2022-06-29	2022-05-06T09:30:02	2023-01-09	2022-03-12T14:26	109.50.92.119	CraigHughes@Talane.biz	Heath Drive 38
+-2147413967	true	-75	30533	-5435	-727385447	32929830	9577.564	1.334766997510087E9	39973144022098028.800	5886463393340733.108	2022-06-23	2022-05-10T19:13:50	2022-01-17	2022-11-26T22:49:36	157.38.90.25	JoshuaLewis@Jayo.mil	Loeprich Crossing 43
+-2147380173	true	-79	-5785	9752	1851350218	1121852298	25652.402	-1.618061059513558E9	95821873014545736.897	38923569966532828.626	2022-10-30	2022-05-02T17:06:33	2022-08-11	2022-02-08T10:19:47	217.198.98.239	JoseBoyd@Voonder.info	Lawn Lane 78
+-2147374459	false	-118	-30267	-14606	262497842	-1811881704	8211.805	2.37851933046663E8	37354136531251060.755	63024710145324035.720	2022-10-11	2022-01-17T10:20:18	2022-04-12	2022-10-24T18:14:38	16.243.195.81	BrendaBoyd@Talane.net	Annamark Pass 72
+-2147369329	false	-121	-22859	4733	-378861997	385323541	-22969.846	1.483825622420542E9	50940877800950041.950	87108729227937387.294	2022-06-05	2022-08-18T05:39:56	2022-08-21	2022-12-12T08:43:59	16.27.107.167	PhyllisSmith@Zoombox.org	Village Green Terrace 55
+-2147367329	true	84	21471	-29331	1823545950	1200800855	-13832.219	8.01505090724918E8	45495296019797580.477	45196001436348967.557	2022-02-17	2022-05-23T01:44:31	2022-08-01	2022-08-16T10:32:36	84.110.209.128	vLane@Dablist.edu	Packers Street 34
+-2147339287	true	62	28989	-32018	650184880	-365849435	-21644.414	-7.8648426469503E7	92593387160450273.870	39588697152489527.185	2022-07-23	2023-01-03T11:54:35	2022-08-02	2022-05-19T18:35:36	30.194.6.115	veniam@Thoughtstorm.mil	Basil Street 79
+-2147336695	false	42	-7202	27919	1898713395	1177326785	-302.0104	-1.268944460183375E9	61604656210729534.717	6683002058708470.832	2022-08-20	2022-08-14T01:41:12	2022-11-02	2022-05-15T04:22:07	36.86.77.214	delectus_maiores_fugit@Rhyzio.org	Briar Crest Crossing 37
+-2147330925	false	-122	-21211	-2331	1906695924	-1342280417	5545.3013	-1.286038914681617E9	31911132334645267.930	84364209624711210.131	2022-02-16	2022-03-11T12:05:33	2022-11-24	2022-12-17T19:56:16	6.87.14.74	rCampbell@Riffpath.com	Forest Run Terrace 13
+
+-- !sql --
+-2145739104	true	10	-22603	6132	-984517723	138439036	8683.904	1.681202635040786E9	49683339998558535.395	38251259739648714.297	2022-04-26	2022-09-12T00:32:18	2022-11-20	2023-01-09T16:19:06	180.215.212.86	KathyRoberts@Talane.info	Darwin Center 26
+-2140012242	false	10	30893	-16192	-175522451	-1382546546	21324.643	2.017216342012696E9	41477187479096470.647	25445001389089818.791	2022-11-06	2022-09-02T12:04:05	2022-05-29	2022-02-04T22:21:46	24.25.69.81	nam_quasi@Photospace.mil	Jay Way 9
+-2130269306	false	10	30342	-18732	1461226453	-1257020753	-10751.815	3.44246067782915E8	2456538047280540.838	37394928326629689.946	2022-11-28	2022-05-04T20:40:19	2022-08-25	2022-03-18T10:17:35	179.198.200.96	eFuller@Skynoodle.com	Tennyson Street 83
+-2122709724	true	10	-8985	-30620	-1375603501	631094037	14711.055	-1.210030062083139E9	96220820029888063.156	42161382030214480.728	2022-05-28	2023-01-03T20:44:27	2022-06-11	2022-07-26T22:49:22	13.249.135.222	uDixon@Shufflebeat.name	Riverside Parkway 72
+-2117749737	false	10	26335	30644	1841596444	283308539	18848.148	3.5339747538014E8	11924963560520504.166	28287350935413049.601	2022-08-01	2022-04-21T02:28:54	2022-02-27	2022-09-02T17:11:17	183.108.102.1	pHanson@Cogibox.com	Maple Wood Street 40
+-2113239713	false	10	27624	31311	711781944	-1838033894	-12299.482	-1.88263132184351E9	9480201396831049.605	52114965946122870.302	2022-06-11	2022-08-31T08:54:30	2022-03-26	2023-01-08T23:28:27	200.161.156.176	et@Buzzster.net	Westport Drive 82
+-2107773486	false	10	27096	10368	1579374450	1370327646	-15339.031	2.110010890135424E9	54514853031265543.378	38546969634312019.180	2022-12-31	2022-10-07T10:18:27	2022-10-01	2022-07-09T11:41:11	121.120.227.53	JuliaDean@Plambee.com	Sugar Crossing 43
+-2107242025	true	10	25215	26566	1292568651	-2126795906	11912.074	-2.140044503516609E9	98695561934257164.368	18845397264645075.775	2022-05-21	2022-09-24T23:00:21	2022-02-12	2022-11-24T19:17:03	141.226.90.50	AnnaGonzalez@Eimbee.mil	Cody Street 78
+-2106969609	true	10	29572	16738	1736115820	-957295886	-13319.206	-1.333603562816737E9	91224478600376111.942	69457425159617037.453	2022-09-06	2022-05-08T19:52:36	2022-04-05	2022-08-17T19:23:31	222.79.139.99	WalterFox@Voomm.net	Oxford Alley 77
+-2102307005	true	10	-23674	24613	-1810828490	-47095409	-14686.167	2.072108685694799E9	39847820962230526.125	584354832299375.156	2022-03-27	2022-02-11T13:46:06	2022-12-25	2022-11-28T09:37:49	213.146.33.250	JuliaSimmons@Zazio.info	Eagle Crest Terrace 84
+
diff --git a/regression-test/suites/point_query_p0/load.groovy b/regression-test/suites/point_query_p0/load.groovy
new file mode 100644
index 0000000000..7ac12d0c35
--- /dev/null
+++ b/regression-test/suites/point_query_p0/load.groovy
@@ -0,0 +1,101 @@
+// 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_point_query_load", "p0") {
+
+    def dataFile = """${getS3Url()}/regression/datatypes/test_scalar_types_10w.csv"""
+
+    // define dup key table1
+    def testTable = "tbl_scalar_types_dup"
+    sql "DROP TABLE IF EXISTS ${testTable} FORCE"
+    sql """
+        CREATE TABLE IF NOT EXISTS ${testTable} (
+            `k1` bigint(11) NULL,
+            `c_bool` boolean NULL,
+            `c_tinyint` tinyint(4) NULL,
+            `c_smallint` smallint(6) NULL,
+            `c_int` int(11) NULL,
+            `c_bigint` bigint(20) NULL,
+            `c_largeint` largeint(40) NULL,
+            `c_float` float NULL,
+            `c_double` double NULL,
+            `c_decimal` decimal(20, 3) NULL,
+            `c_decimalv3` decimalv3(20, 3) NULL,
+            `c_date` date NULL,
+            `c_datetime` datetime NULL,
+            `c_datev2` datev2 NULL,
+            `c_datetimev2` datetimev2(0) NULL,
+            `c_char` char(15) NULL,
+            `c_varchar` varchar(100) NULL,
+            `c_string` text NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(`k1`)
+        COMMENT 'OLAP'
+        DISTRIBUTED BY HASH(`k1`) BUCKETS 10
+        PROPERTIES("replication_num" = "1", "store_row_column" = "true");
+        """
+
+    // load data
+    streamLoad {
+        table testTable
+        file dataFile
+        time 60000
+
+        check { result, exception, startTime, endTime ->
+            if (exception != null) {
+                throw exception
+            }
+            log.info("Stream load result: ${result}".toString())
+            def json = parseJson(result)
+            assertEquals(100000, json.NumberTotalRows)
+            assertEquals(100000, json.NumberLoadedRows)
+        }
+    }
+    createMV ("""CREATE MATERIALIZED VIEW mv_${testTable} AS SELECT c_tinyint, c_bool, k1, c_smallint, c_int, c_bigint, c_largeint, c_float, c_double,  c_decimal, c_decimalv3, c_date, c_datetime, c_datev2, c_datetimev2, c_char, c_varchar, c_string FROM ${testTable} ORDER BY c_tinyint, c_bool, k1""")
+
+    sql "set topn_opt_limit_threshold = 100"
+    explain {
+        sql("SELECT * from ${testTable} where c_tinyint = 10 order by 1, 2, 3 limit 10")
+        contains "(mv_${testTable})"
+        contains "OPT TWO PHASE"
+    }
+    qt_sql "SELECT * from ${testTable} order by 1, 2, 3 limit 10"
+    qt_sql "SELECT * from ${testTable} where c_tinyint = 10 order by 1, 2, 3 limit 10 "
+
+    sql """
+          ALTER table ${testTable} MODIFY COLUMN c_int BIGINT;
+          """
+    def getJobState = { tableName ->
+          def jobStateResult = sql """  SHOW ALTER TABLE COLUMN WHERE IndexName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
+          return jobStateResult[0][9]
+     }
+    int max_try_time = 100
+     while (max_try_time--){
+          String result = getJobState(testTable)
+          if (result == "FINISHED") {
+               break
+          } else {
+               sleep(2000)
+               if (max_try_time < 1){
+                    assertEquals(1,2)
+               }
+          }
+     }
+    sql "INSERT INTO ${testTable} SELECT * from ${testTable}"
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org