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

morningman 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 151842a1fe [feature](inverted index)WIP inverted index api: SQL syntax 
and metadata (#13430)
151842a1fe is described below

commit 151842a1fe7f431a458446278a43f974e28b2883
Author: Kang <kxiao.ti...@gmail.com>
AuthorDate: Tue Nov 8 23:46:53 2022 +0800

    [feature](inverted index)WIP inverted index api: SQL syntax and metadata 
(#13430)
    
    Introduce a SQL syntax for creating inverted index and related metadata 
changes.
    
    ```
    -- create table with INVERTED index
    
    CREATE TABLE httplogs (
      ts datetime,
      clientip varchar(20),
      request string,
      status smallint,
      size int,
      INDEX idx_size (size) USING INVERTED,
      INDEX idx_status (status) USING INVERTED,
      INDEX idx_clientip (clientip) USING INVERTED PROPERTIES("parser"="none")
    )
    DUPLICATE KEY(ts)
    DISTRIBUTED BY RANDOM BUCKETS 10
    
    -- add an INVERTED index  to a table
    
    CREATE INDEX idx_request ON httplogs(request) USING INVERTED 
PROPERTIES("parser"="english");
    ```
---
 be/src/olap/CMakeLists.txt                         |   1 +
 be/src/olap/inverted_index_parser.cpp              |  65 ++++++++
 be/src/olap/inverted_index_parser.h                |  46 ++++++
 be/src/olap/tablet_meta.cpp                        |  35 +++++
 be/src/olap/tablet_schema.cpp                      | 120 +++++++++++++++
 be/src/olap/tablet_schema.h                        |  29 ++++
 fe/fe-core/src/main/cup/sql_parser.cup             |  15 +-
 .../apache/doris/analysis/CreateIndexClause.java   |   6 +-
 .../org/apache/doris/analysis/CreateTableStmt.java |   5 +-
 .../java/org/apache/doris/analysis/IndexDef.java   |  52 ++++++-
 .../apache/doris/analysis/InvertedIndexUtil.java   |  56 +++++++
 .../org/apache/doris/analysis/ShowIndexStmt.java   |   1 +
 .../main/java/org/apache/doris/catalog/Index.java  |  56 ++++++-
 .../java/org/apache/doris/qe/ShowExecutor.java     |   2 +-
 fe/fe-core/src/main/jflex/sql_scanner.flex         |   1 +
 .../doris/analysis/CreateIndexClauseTest.java      |   2 +-
 .../org/apache/doris/analysis/IndexDefTest.java    |   6 +-
 .../org/apache/doris/catalog/OlapTableTest.java    |   4 +-
 .../persist/TableAddOrDropColumnsInfoTest.java     |   2 +-
 gensrc/proto/olap_file.proto                       |  15 ++
 gensrc/thrift/Descriptors.thrift                   |   6 +-
 .../data/index_p0/test_bitmap_index.out            |  92 ++++++------
 .../test_decimal_bitmap_index_multi_page.out       |   2 +-
 .../suites/index_p0/test_index_meta.groovy         | 167 +++++++++++++++++++++
 24 files changed, 710 insertions(+), 76 deletions(-)

diff --git a/be/src/olap/CMakeLists.txt b/be/src/olap/CMakeLists.txt
index 225f60dad2..f46dd6259d 100644
--- a/be/src/olap/CMakeLists.txt
+++ b/be/src/olap/CMakeLists.txt
@@ -41,6 +41,7 @@ add_library(Olap STATIC
     file_helper.cpp
     generic_iterators.cpp
     hll.cpp
+    inverted_index_parser.cpp
     bloom_filter_predicate.cpp
     like_column_predicate.cpp
     key_coder.cpp
diff --git a/be/src/olap/inverted_index_parser.cpp 
b/be/src/olap/inverted_index_parser.cpp
new file mode 100644
index 0000000000..9407b52ee4
--- /dev/null
+++ b/be/src/olap/inverted_index_parser.cpp
@@ -0,0 +1,65 @@
+// 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.
+
+#include "olap/inverted_index_parser.h"
+
+#include "util/string_util.h"
+
+namespace doris {
+
+std::string inverted_index_parser_type_to_string(InvertedIndexParserType 
parser_type) {
+    switch (parser_type) {
+    case InvertedIndexParserType::PARSER_NONE:
+        return INVERTED_INDEX_PARSER_NONE;
+    case InvertedIndexParserType::PARSER_STANDARD:
+        return INVERTED_INDEX_PARSER_STANDARD;
+    case InvertedIndexParserType::PARSER_ENGLISH:
+        return INVERTED_INDEX_PARSER_ENGLISH;
+    case InvertedIndexParserType::PARSER_CHINESE:
+        return INVERTED_INDEX_PARSER_CHINESE;
+    default:
+        return INVERTED_INDEX_PARSER_UNKNOWN;
+    }
+
+    return INVERTED_INDEX_PARSER_UNKNOWN;
+}
+
+InvertedIndexParserType get_inverted_index_parser_type_from_string(const 
std::string& parser_str) {
+    auto parser_str_lower = to_lower(parser_str);
+    if (parser_str_lower == INVERTED_INDEX_PARSER_NONE) {
+        return InvertedIndexParserType::PARSER_NONE;
+    } else if (parser_str_lower == INVERTED_INDEX_PARSER_STANDARD) {
+        return InvertedIndexParserType::PARSER_STANDARD;
+    } else if (parser_str_lower == INVERTED_INDEX_PARSER_ENGLISH) {
+        return InvertedIndexParserType::PARSER_ENGLISH;
+    } else if (parser_str_lower == INVERTED_INDEX_PARSER_CHINESE) {
+        return InvertedIndexParserType::PARSER_CHINESE;
+    }
+
+    return InvertedIndexParserType::PARSER_UNKNOWN;
+}
+
+std::string get_parser_string_from_properties(
+        const std::map<std::string, std::string>& properties) {
+    if (properties.find(INVERTED_INDEX_PARSER_KEY) != properties.end()) {
+        return properties.at(INVERTED_INDEX_PARSER_KEY);
+    } else {
+        return INVERTED_INDEX_PARSER_NONE;
+    }
+}
+
+} // namespace doris
diff --git a/be/src/olap/inverted_index_parser.h 
b/be/src/olap/inverted_index_parser.h
new file mode 100644
index 0000000000..0c870aa355
--- /dev/null
+++ b/be/src/olap/inverted_index_parser.h
@@ -0,0 +1,46 @@
+// 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.
+
+#pragma once
+
+#include <map>
+#include <string>
+
+namespace doris {
+
+enum class InvertedIndexParserType {
+    PARSER_UNKNOWN = 0,
+    PARSER_NONE = 1,
+    PARSER_STANDARD = 2,
+    PARSER_ENGLISH = 3,
+    PARSER_CHINESE = 4,
+};
+
+const std::string INVERTED_INDEX_PARSER_KEY = "parser";
+const std::string INVERTED_INDEX_PARSER_UNKNOWN = "unknown";
+const std::string INVERTED_INDEX_PARSER_NONE = "none";
+const std::string INVERTED_INDEX_PARSER_STANDARD = "standard";
+const std::string INVERTED_INDEX_PARSER_ENGLISH = "english";
+const std::string INVERTED_INDEX_PARSER_CHINESE = "chinese";
+
+std::string inverted_index_parser_type_to_string(InvertedIndexParserType 
parser_type);
+
+InvertedIndexParserType get_inverted_index_parser_type_from_string(const 
std::string& parser_str);
+
+std::string get_parser_string_from_properties(const std::map<std::string, 
std::string>& properties);
+
+} // namespace doris
diff --git a/be/src/olap/tablet_meta.cpp b/be/src/olap/tablet_meta.cpp
index 70348ba110..010b2217c6 100644
--- a/be/src/olap/tablet_meta.cpp
+++ b/be/src/olap/tablet_meta.cpp
@@ -169,6 +169,41 @@ TabletMeta::TabletMeta(int64_t table_id, int64_t 
partition_id, int64_t tablet_id
         }
     }
 
+    // copy index meta
+    if (tablet_schema.__isset.indexes) {
+        for (auto& index : tablet_schema.indexes) {
+            TabletIndexPB* index_pb = schema->add_index();
+            index_pb->set_index_id(index.index_id);
+            index_pb->set_index_name(index.index_name);
+            // init col_unique_id in index at be side, since col_unique_id may 
be -1 at fe side
+            // get column unique id by name
+            for (auto column_name : index.columns) {
+                for (auto column : schema->column()) {
+                    if (iequal(column.name(), column_name)) {
+                        index_pb->add_col_unique_id(column.unique_id());
+                    }
+                }
+            }
+            switch (index.index_type) {
+            case TIndexType::BITMAP:
+                index_pb->set_index_type(IndexType::BITMAP);
+                break;
+            case TIndexType::INVERTED:
+                index_pb->set_index_type(IndexType::INVERTED);
+                break;
+            case TIndexType::BLOOMFILTER:
+                index_pb->set_index_type(IndexType::BLOOMFILTER);
+                break;
+            }
+            if (index.__isset.properties) {
+                auto properties = index_pb->mutable_properties();
+                for (auto kv : index.properties) {
+                    (*properties)[kv.first] = kv.second;
+                }
+            }
+        }
+    }
+
     schema->set_next_column_unique_id(next_unique_id);
     if (has_bf_columns && tablet_schema.__isset.bloom_filter_fpp) {
         schema->set_bf_fpp(tablet_schema.bloom_filter_fpp);
diff --git a/be/src/olap/tablet_schema.cpp b/be/src/olap/tablet_schema.cpp
index 9dcc7a5793..fe4b353e5a 100644
--- a/be/src/olap/tablet_schema.cpp
+++ b/be/src/olap/tablet_schema.cpp
@@ -469,6 +469,62 @@ vectorized::AggregateFunctionPtr 
TabletColumn::get_aggregate_function(
             agg_name, argument_types, {}, 
argument_types.back()->is_nullable());
 }
 
+void TabletIndex::init_from_thrift(const TOlapTableIndex& index,
+                                   const TabletSchema& tablet_schema) {
+    _index_id = index.index_id;
+    _index_name = index.index_name;
+    // init col_unique_id in index at be side, since col_unique_id may be -1 
at fe side
+    // get column unique id by name
+    std::vector<int32_t> col_unique_ids(index.columns.size());
+    for (size_t i = 0; i < index.columns.size(); i++) {
+        col_unique_ids[i] = tablet_schema.column(index.columns[i]).unique_id();
+    }
+    _col_unique_ids = std::move(col_unique_ids);
+
+    switch (index.index_type) {
+    case TIndexType::BITMAP:
+        _index_type = IndexType::BITMAP;
+        break;
+    case TIndexType::INVERTED:
+        _index_type = IndexType::INVERTED;
+        break;
+    case TIndexType::BLOOMFILTER:
+        _index_type = IndexType::BLOOMFILTER;
+        break;
+    }
+    if (index.__isset.properties) {
+        for (auto kv : index.properties) {
+            _properties[kv.first] = kv.second;
+        }
+    }
+}
+
+void TabletIndex::init_from_pb(const TabletIndexPB& index) {
+    _index_id = index.index_id();
+    _index_name = index.index_name();
+    _col_unique_ids.clear();
+    for (auto col_unique_id : index.col_unique_id()) {
+        _col_unique_ids.push_back(col_unique_id);
+    }
+    _index_type = index.index_type();
+    for (auto& kv : index.properties()) {
+        _properties[kv.first] = kv.second;
+    }
+}
+
+void TabletIndex::to_schema_pb(TabletIndexPB* index) const {
+    index->set_index_id(_index_id);
+    index->set_index_name(_index_name);
+    index->clear_col_unique_id();
+    for (auto col_unique_id : _col_unique_ids) {
+        index->add_col_unique_id(col_unique_id);
+    }
+    index->set_index_type(_index_type);
+    for (auto& kv : _properties) {
+        (*index->mutable_properties())[kv.first] = kv.second;
+    }
+}
+
 void TabletSchema::append_column(TabletColumn column, bool is_dropped_column) {
     if (column.is_key()) {
         _num_key_columns++;
@@ -522,6 +578,11 @@ void TabletSchema::init_from_pb(const TabletSchemaPB& 
schema) {
         _cols.emplace_back(std::move(column));
         _num_columns++;
     }
+    for (auto& index_pb : schema.index()) {
+        TabletIndex index;
+        index.init_from_pb(index_pb);
+        _indexes.emplace_back(std::move(index));
+    }
     _num_short_key_columns = schema.num_short_key_columns();
     _num_rows_per_row_block = schema.num_rows_per_row_block();
     _compress_kind = schema.compress_kind();
@@ -647,6 +708,10 @@ void TabletSchema::to_schema_pb(TabletSchemaPB* 
tablet_schema_pb) const {
         ColumnPB* column = tablet_schema_pb->add_column();
         col.to_schema_pb(column);
     }
+    for (auto& index : _indexes) {
+        auto index_pb = tablet_schema_pb->add_index();
+        index.to_schema_pb(index_pb);
+    }
     tablet_schema_pb->set_num_short_key_columns(_num_short_key_columns);
     tablet_schema_pb->set_num_rows_per_row_block(_num_rows_per_row_block);
     tablet_schema_pb->set_compress_kind(_compress_kind);
@@ -710,11 +775,66 @@ const TabletColumn& TabletSchema::column_by_uid(int32_t 
col_unique_id) const {
     return _cols.at(_field_id_to_index.at(col_unique_id));
 }
 
+void TabletSchema::update_indexes_from_thrift(const 
std::vector<doris::TOlapTableIndex>& tindexes) {
+    std::vector<TabletIndex> indexes;
+    for (auto& tindex : tindexes) {
+        TabletIndex index;
+        index.init_from_thrift(tindex, *this);
+        indexes.emplace_back(std::move(index));
+    }
+    _indexes = std::move(indexes);
+}
+
 const TabletColumn& TabletSchema::column(const std::string& field_name) const {
     const auto& found = _field_name_to_index.find(field_name);
     return _cols[found->second];
 }
 
+std::vector<const TabletIndex*> TabletSchema::get_indexes_for_column(int32_t 
col_unique_id) const {
+    std::vector<const TabletIndex*> indexes_for_column;
+
+    // TODO use more efficient impl
+    for (size_t i = 0; i < _indexes.size(); i++) {
+        for (int32_t id : _indexes[i].col_unique_ids()) {
+            if (id == col_unique_id) {
+                indexes_for_column.push_back(&(_indexes[i]));
+            }
+        }
+    }
+
+    return indexes_for_column;
+}
+
+bool TabletSchema::has_inverted_index(int32_t col_unique_id) const {
+    // TODO use more efficient impl
+    for (size_t i = 0; i < _indexes.size(); i++) {
+        if (_indexes[i].index_type() == IndexType::INVERTED) {
+            for (int32_t id : _indexes[i].col_unique_ids()) {
+                if (id == col_unique_id) {
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+const TabletIndex* TabletSchema::get_inverted_index(int32_t col_unique_id) 
const {
+    // TODO use more efficient impl
+    for (size_t i = 0; i < _indexes.size(); i++) {
+        if (_indexes[i].index_type() == IndexType::INVERTED) {
+            for (int32_t id : _indexes[i].col_unique_ids()) {
+                if (id == col_unique_id) {
+                    return &(_indexes[i]);
+                }
+            }
+        }
+    }
+
+    return nullptr;
+}
+
 vectorized::Block TabletSchema::create_block(
         const std::vector<uint32_t>& return_columns,
         const std::unordered_set<uint32_t>* tablet_columns_need_convert_null) 
const {
diff --git a/be/src/olap/tablet_schema.h b/be/src/olap/tablet_schema.h
index 300b603e83..6702901e83 100644
--- a/be/src/olap/tablet_schema.h
+++ b/be/src/olap/tablet_schema.h
@@ -117,6 +117,28 @@ private:
 bool operator==(const TabletColumn& a, const TabletColumn& b);
 bool operator!=(const TabletColumn& a, const TabletColumn& b);
 
+class TabletSchema;
+
+class TabletIndex {
+public:
+    void init_from_thrift(const TOlapTableIndex& index, const TabletSchema& 
tablet_schema);
+    void init_from_pb(const TabletIndexPB& index);
+    void to_schema_pb(TabletIndexPB* index) const;
+
+    const int64_t index_id() const { return _index_id; }
+    const std::string& index_name() const { return _index_name; }
+    const IndexType index_type() const { return _index_type; }
+    const vector<int32_t>& col_unique_ids() const { return _col_unique_ids; }
+    const std::map<string, string>& properties() const { return _properties; }
+
+private:
+    int64_t _index_id;
+    std::string _index_name;
+    IndexType _index_type;
+    std::vector<int32_t> _col_unique_ids;
+    std::map<string, string> _properties;
+};
+
 class TabletSchema {
 public:
     // TODO(yingchun): better to make constructor as private to avoid
@@ -161,6 +183,12 @@ public:
     int32_t sequence_col_idx() const { return _sequence_col_idx; }
     segment_v2::CompressionTypePB compression_type() const { return 
_compression_type; }
 
+    const std::vector<TabletIndex>& indexes() const { return _indexes; }
+    std::vector<const TabletIndex*> get_indexes_for_column(int32_t 
col_unique_id) const;
+    bool has_inverted_index(int32_t col_unique_id) const;
+    const TabletIndex* get_inverted_index(int32_t col_unique_id) const;
+    void update_indexes_from_thrift(const std::vector<doris::TOlapTableIndex>& 
indexes);
+
     int32_t schema_version() const { return _schema_version; }
     void clear_columns();
     vectorized::Block create_block(
@@ -196,6 +224,7 @@ private:
     SortType _sort_type = SortType::LEXICAL;
     size_t _sort_col_num = 0;
     std::vector<TabletColumn> _cols;
+    std::vector<TabletIndex> _indexes;
     std::unordered_map<std::string, int32_t> _field_name_to_index;
     std::unordered_map<int32_t, int32_t> _field_id_to_index;
     size_t _num_columns = 0;
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup 
b/fe/fe-core/src/main/cup/sql_parser.cup
index a9cf6b3dea..adec23db2c 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -409,6 +409,7 @@ terminal String
     KW_IS,
     KW_ISNULL,
     KW_ISOLATION,
+    KW_INVERTED,
     KW_JOB,
     KW_JOIN,
     KW_JSON,
@@ -1830,9 +1831,9 @@ create_stmt ::=
     {:
         RESULT = new CreateMultiTableMaterializedViewStmt(mvName, buildMethod, 
refreshInfo, keyDesc, partitionDesc, distributionDesc, properties, query);
     :}
-    | KW_CREATE KW_INDEX opt_if_not_exists:ifNotExists ident:indexName KW_ON 
table_name:tableName LPAREN ident_list:cols RPAREN opt_index_type:indexType 
opt_comment:comment
+    | KW_CREATE KW_INDEX opt_if_not_exists:ifNotExists ident:indexName KW_ON 
table_name:tableName LPAREN ident_list:cols RPAREN opt_index_type:indexType 
opt_properties:properties opt_comment:comment
     {:
-        RESULT = new AlterTableStmt(tableName, Lists.newArrayList(new 
CreateIndexClause(tableName, new IndexDef(indexName, ifNotExists, cols, 
indexType, comment), false)));
+        RESULT = new AlterTableStmt(tableName, Lists.newArrayList(new 
CreateIndexClause(tableName, new IndexDef(indexName, ifNotExists, cols, 
indexType, properties, comment), false)));
     :}
     /* resource */
     | KW_CREATE opt_external:isExternal KW_RESOURCE 
opt_if_not_exists:ifNotExists ident_or_text:resourceName 
opt_properties:properties
@@ -3142,9 +3143,9 @@ column_definition ::=
     ;
 
 index_definition ::=
-    KW_INDEX opt_if_not_exists:ifNotExists ident:indexName LPAREN 
ident_list:cols RPAREN opt_index_type:indexType opt_comment:comment
+    KW_INDEX opt_if_not_exists:ifNotExists ident:indexName LPAREN 
ident_list:cols RPAREN opt_index_type:indexType opt_properties:properties 
opt_comment:comment
     {:
-        RESULT = new IndexDef(indexName, ifNotExists, cols, indexType, 
comment);
+        RESULT = new IndexDef(indexName, ifNotExists, cols, indexType, 
properties, comment);
     :}
     ;
 
@@ -3181,6 +3182,10 @@ opt_index_type ::=
     {:
         RESULT = IndexDef.IndexType.BITMAP;
     :}
+    | KW_USING KW_INVERTED
+    {:
+        RESULT = IndexDef.IndexType.INVERTED;
+    :}
     ;
 
 opt_if_exists ::=
@@ -6489,6 +6494,8 @@ keyword ::=
     {: RESULT = id; :}
     | KW_INDEXES:id
     {: RESULT = id; :}
+    | KW_INVERTED:id
+    {: RESULT = id; :}
     | KW_ISNULL:id
     {: RESULT = id; :}
     | KW_ISOLATION:id
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateIndexClause.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateIndexClause.java
index d1ff4006ba..632492191c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateIndexClause.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateIndexClause.java
@@ -18,6 +18,7 @@
 package org.apache.doris.analysis;
 
 import org.apache.doris.alter.AlterOpType;
+import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.Index;
 import org.apache.doris.common.AnalysisException;
 
@@ -70,8 +71,9 @@ public class CreateIndexClause extends AlterTableClause {
             throw new AnalysisException("index definition expected.");
         }
         indexDef.analyze();
-        this.index = new Index(indexDef.getIndexName(), indexDef.getColumns(), 
indexDef.getIndexType(),
-                indexDef.getComment());
+        this.index = new Index(Env.getCurrentEnv().getNextId(), 
indexDef.getIndexName(),
+                indexDef.getColumns(), indexDef.getIndexType(),
+                indexDef.getProperties(), indexDef.getComment());
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java
index 7ba06377a0..7f33428da3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java
@@ -488,8 +488,9 @@ public class CreateTableStmt extends DdlStmt {
                                 + indexColName);
                     }
                 }
-                indexes.add(new Index(indexDef.getIndexName(), 
indexDef.getColumns(), indexDef.getIndexType(),
-                        indexDef.getComment()));
+                indexes.add(new Index(Env.getCurrentEnv().getNextId(), 
indexDef.getIndexName(),
+                        indexDef.getColumns(), indexDef.getIndexType(),
+                        indexDef.getProperties(), indexDef.getComment()));
                 distinct.add(indexDef.getIndexName());
                 
distinctCol.add(indexDef.getColumns().stream().map(String::toUpperCase).collect(Collectors.toList()));
             }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IndexDef.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/IndexDef.java
index fca80403c1..4df18a9879 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IndexDef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IndexDef.java
@@ -24,7 +24,9 @@ import org.apache.doris.common.AnalysisException;
 
 import com.google.common.base.Strings;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.TreeSet;
 
 public class IndexDef {
@@ -33,8 +35,10 @@ public class IndexDef {
     private List<String> columns;
     private IndexType indexType;
     private String comment;
+    private Map<String, String> properties;
 
-    public IndexDef(String indexName, boolean ifNotExists, List<String> 
columns, IndexType indexType, String comment) {
+    public IndexDef(String indexName, boolean ifNotExists, List<String> 
columns, IndexType indexType,
+                    Map<String, String> properties, String comment) {
         this.indexName = indexName;
         this.ifNotExists = ifNotExists;
         this.columns = columns;
@@ -48,12 +52,18 @@ public class IndexDef {
         } else {
             this.comment = comment;
         }
+        if (properties == null) {
+            this.properties = new HashMap<>();
+        } else {
+            this.properties = properties;
+        }
     }
 
     public void analyze() throws AnalysisException {
-        if (indexType == IndexDef.IndexType.BITMAP) {
+        if (indexType == IndexDef.IndexType.BITMAP
+                || indexType == IndexDef.IndexType.INVERTED) {
             if (columns == null || columns.size() != 1) {
-                throw new AnalysisException("bitmap index can only apply to a 
single column.");
+                throw new AnalysisException(indexType.toString() + " index can 
only apply to a single column.");
             }
             if (Strings.isNullOrEmpty(indexName)) {
                 throw new AnalysisException("index name cannot be blank.");
@@ -93,6 +103,19 @@ public class IndexDef {
         if (indexType != null) {
             sb.append(" USING ").append(indexType.toString());
         }
+        if (properties != null && properties.size() > 0) {
+            sb.append(" PROPERTIES(");
+            first = true;
+            for (Map.Entry<String, String> e : properties.entrySet()) {
+                if (first) {
+                    first = false;
+                } else {
+                    sb.append(", ");
+                }
+                
sb.append("\"").append(e.getKey()).append("\"=").append("\"").append(e.getValue()).append("\"");
+            }
+            sb.append(")");
+        }
         if (comment != null) {
             sb.append(" COMMENT '" + comment + "'");
         }
@@ -116,6 +139,10 @@ public class IndexDef {
         return indexType;
     }
 
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
     public String getComment() {
         return comment;
     }
@@ -126,29 +153,38 @@ public class IndexDef {
 
     public enum IndexType {
         BITMAP,
+        INVERTED,
+        BLOOMFILTER,
+    }
 
+    public boolean isInvertedIndex() {
+        return (this.indexType == IndexType.INVERTED);
     }
 
     public void checkColumn(Column column, KeysType keysType) throws 
AnalysisException {
-        if (indexType == IndexType.BITMAP) {
+        if (indexType == IndexType.BITMAP || indexType == IndexType.INVERTED 
|| indexType == IndexType.BLOOMFILTER) {
             String indexColName = column.getName();
             PrimitiveType colType = column.getDataType();
             if (!(colType.isDateType() || colType.isDecimalV2Type() || 
colType.isDecimalV3Type()
                     || colType.isFixedPointType() || colType.isStringType() || 
colType == PrimitiveType.BOOLEAN)) {
-                throw new AnalysisException(colType + " is not supported in 
bitmap index. "
+                throw new AnalysisException(colType + " is not supported in " 
+ indexType.toString() + " index. "
                         + "invalid column: " + indexColName);
             } else if ((keysType == KeysType.AGG_KEYS && !column.isKey())) {
-                throw new AnalysisException(
-                        "BITMAP index only used in columns of 
DUP_KEYS/UNIQUE_KEYS table or key columns of"
+                throw new AnalysisException(indexType.toString()
+                        + " index only used in columns of DUP_KEYS/UNIQUE_KEYS 
table or key columns of"
                                 + " AGG_KEYS table. invalid column: " + 
indexColName);
             }
+
+            if (indexType == IndexType.INVERTED) {
+                InvertedIndexUtil.checkInvertedIndexParser(indexColName, 
colType, properties);
+            }
         } else {
             throw new AnalysisException("Unsupported index type: " + 
indexType);
         }
     }
 
     public void checkColumns(List<Column> columns, KeysType keysType) throws 
AnalysisException {
-        if (indexType == IndexType.BITMAP) {
+        if (indexType == IndexType.BITMAP || indexType == IndexType.INVERTED 
|| indexType == IndexType.BLOOMFILTER) {
             for (Column col : columns) {
                 checkColumn(col, keysType);
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/InvertedIndexUtil.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/InvertedIndexUtil.java
new file mode 100644
index 0000000000..412935ab91
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/InvertedIndexUtil.java
@@ -0,0 +1,56 @@
+// 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.
+
+package org.apache.doris.analysis;
+
+import org.apache.doris.catalog.PrimitiveType;
+import org.apache.doris.common.AnalysisException;
+
+import java.util.Map;
+
+public class InvertedIndexUtil {
+
+    public static String INVERTED_INDEX_PARSER_KEY = "parser";
+    public static String INVERTED_INDEX_PARSER_UNKNOWN = "unknown";
+    public static String INVERTED_INDEX_PARSER_NONE = "none";
+    public static String INVERTED_INDEX_PARSER_STANDARD = "standard";
+    public static String INVERTED_INDEX_PARSER_ENGLISH = "english";
+    public static String INVERTED_INDEX_PARSER_CHINESE = "chinese";
+
+    public static String getInvertedIndexParser(Map<String, String> 
properties) {
+        String parser = properties == null ? null : 
properties.get(INVERTED_INDEX_PARSER_KEY);
+        // default is "none" if not set
+        return parser != null ? parser : INVERTED_INDEX_PARSER_NONE;
+    }
+
+    public static void checkInvertedIndexParser(String indexColName, 
PrimitiveType colType,
+            Map<String, String> properties) throws AnalysisException {
+        String parser = getInvertedIndexParser(properties);
+        if (colType.isStringType()) {
+            if (!(parser.equals(INVERTED_INDEX_PARSER_NONE)
+                    || parser.equals(INVERTED_INDEX_PARSER_STANDARD)
+                        || parser.equals(INVERTED_INDEX_PARSER_ENGLISH)
+                            || parser.equals(INVERTED_INDEX_PARSER_CHINESE))) {
+                throw new AnalysisException("INVERTED index parser: " + parser
+                    + " is invalid for column: " + indexColName + " of type " 
+ colType);
+            }
+        } else if (!parser.equals(INVERTED_INDEX_PARSER_NONE)) {
+            throw new AnalysisException("INVERTED index with parser: " + parser
+                + " is not supported for column: " + indexColName + " of type 
" + colType);
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowIndexStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowIndexStmt.java
index 38468e5c7c..0a3977f03f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowIndexStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowIndexStmt.java
@@ -46,6 +46,7 @@ public class ShowIndexStmt extends ShowStmt {
                     .addColumn(new Column("Null", 
ScalarType.createVarchar(80)))
                     .addColumn(new Column("Index_type", 
ScalarType.createVarchar(80)))
                     .addColumn(new Column("Comment", 
ScalarType.createVarchar(80)))
+                    .addColumn(new Column("Properties", 
ScalarType.createVarchar(200)))
                     .build();
     private String dbName;
     private TableName tableName;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Index.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Index.java
index b5536faf55..2da8ce35ff 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Index.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Index.java
@@ -18,8 +18,10 @@
 package org.apache.doris.catalog;
 
 import org.apache.doris.analysis.IndexDef;
+import org.apache.doris.analysis.InvertedIndexUtil;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
+import org.apache.doris.common.util.PrintableMap;
 import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.thrift.TIndexType;
 import org.apache.doris.thrift.TOlapTableIndex;
@@ -30,26 +32,37 @@ import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Internal representation of index, including index type, name, columns and 
comments.
  * This class will used in olaptable
  */
 public class Index implements Writable {
+    public static final int INDEX_ID_INIT_VALUE = -1;
+
+    @SerializedName(value = "indexId")
+    private long indexId = -1; // -1 for compatibale
     @SerializedName(value = "indexName")
     private String indexName;
     @SerializedName(value = "columns")
     private List<String> columns;
     @SerializedName(value = "indexType")
     private IndexDef.IndexType indexType;
+    @SerializedName(value = "properties")
+    private Map<String, String> properties;
     @SerializedName(value = "comment")
     private String comment;
 
-    public Index(String indexName, List<String> columns, IndexDef.IndexType 
indexType, String comment) {
+    public Index(long indexId, String indexName, List<String> columns,
+                 IndexDef.IndexType indexType, Map<String, String> properties, 
String comment) {
+        this.indexId = indexId;
         this.indexName = indexName;
         this.columns = columns;
         this.indexType = indexType;
+        this.properties = properties;
         this.comment = comment;
     }
 
@@ -57,9 +70,18 @@ public class Index implements Writable {
         this.indexName = null;
         this.columns = null;
         this.indexType = null;
+        this.properties = null;
         this.comment = null;
     }
 
+    public long getIndexId() {
+        return indexId;
+    }
+
+    public void setIndexId(long indexId) {
+        this.indexId = indexId;
+    }
+
     public String getIndexName() {
         return indexName;
     }
@@ -84,6 +106,26 @@ public class Index implements Writable {
         this.indexType = indexType;
     }
 
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, String> properties) {
+        this.properties = properties;
+    }
+
+    public String getPropertiesString() {
+        if (properties == null || properties.isEmpty()) {
+            return "";
+        }
+
+        return "(" + new PrintableMap(properties, "=", true, false, 
",").toString() + ")";
+    }
+
+    public String getInvertedIndexParser() {
+        return InvertedIndexUtil.getInvertedIndexParser(properties);
+    }
+
     public String getComment() {
         return comment;
     }
@@ -108,7 +150,8 @@ public class Index implements Writable {
     }
 
     public Index clone() {
-        return new Index(indexName, new ArrayList<>(columns), indexType, 
comment);
+        return new Index(indexId, indexName, new ArrayList<>(columns),
+                         indexType, new HashMap<>(properties), comment);
     }
 
     @Override
@@ -133,6 +176,10 @@ public class Index implements Writable {
         if (indexType != null) {
             sb.append(" USING ").append(indexType.toString());
         }
+        if (properties != null && properties.size() > 0) {
+            sb.append(" PROPERTIES");
+            sb.append(getPropertiesString());
+        }
         if (comment != null) {
             sb.append(" COMMENT '" + comment + "'");
         }
@@ -141,11 +188,12 @@ public class Index implements Writable {
 
     public TOlapTableIndex toThrift() {
         TOlapTableIndex tIndex = new TOlapTableIndex();
+        tIndex.setIndexId(indexId);
         tIndex.setIndexName(indexName);
         tIndex.setColumns(columns);
         tIndex.setIndexType(TIndexType.valueOf(indexType.toString()));
-        if (columns != null) {
-            tIndex.setComment(comment);
+        if (properties != null) {
+            tIndex.setProperties(properties);
         }
         return tIndex;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
index 0c7077a84f..f72aab6f0c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
@@ -963,7 +963,7 @@ public class ShowExecutor {
             for (Index index : indexes) {
                 
rows.add(Lists.newArrayList(showStmt.getTableName().toString(), "", 
index.getIndexName(),
                         "", String.join(",", index.getColumns()), "", "", "", 
"",
-                        "", index.getIndexType().name(), index.getComment()));
+                        "", index.getIndexType().name(), index.getComment(), 
index.getPropertiesString()));
             }
         } finally {
             table.readUnlock();
diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex 
b/fe/fe-core/src/main/jflex/sql_scanner.flex
index 4a15fe3521..541322b57a 100644
--- a/fe/fe-core/src/main/jflex/sql_scanner.flex
+++ b/fe/fe-core/src/main/jflex/sql_scanner.flex
@@ -118,6 +118,7 @@ import org.apache.doris.qe.SqlModeHelper;
         keywordMap.put("bin", new Integer(SqlParserSymbols.KW_BIN));
         keywordMap.put("binlog", new Integer(SqlParserSymbols.KW_BINLOG));
         keywordMap.put("bitmap", new Integer(SqlParserSymbols.KW_BITMAP));
+        keywordMap.put("inverted", new Integer(SqlParserSymbols.KW_INVERTED));
         keywordMap.put("bitmap_union", new 
Integer(SqlParserSymbols.KW_BITMAP_UNION));
         keywordMap.put("blob", new Integer(SqlParserSymbols.KW_BLOB));
         keywordMap.put("boolean", new Integer(SqlParserSymbols.KW_BOOLEAN));
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateIndexClauseTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateIndexClauseTest.java
index fe46c0c4af..88aae9c4e2 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateIndexClauseTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateIndexClauseTest.java
@@ -37,7 +37,7 @@ public class CreateIndexClauseTest {
     public void testNormal() throws AnalysisException {
         CreateIndexClause clause = new CreateIndexClause(
                 new TableName(InternalCatalog.INTERNAL_CATALOG_NAME, "db", 
"table"),
-                new IndexDef("index1", false, Lists.newArrayList("col1"), 
IndexDef.IndexType.BITMAP, "balabala"),
+                new IndexDef("index1", false, Lists.newArrayList("col1"), 
IndexDef.IndexType.BITMAP, null, "balabala"),
                 false);
         clause.analyze(analyzer);
         Assert.assertEquals("CREATE INDEX index1 ON `db`.`table` (`col1`) 
USING BITMAP COMMENT 'balabala'",
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/analysis/IndexDefTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/analysis/IndexDefTest.java
index 5f18742cb9..b1072e41fa 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/IndexDefTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/IndexDefTest.java
@@ -29,7 +29,7 @@ public class IndexDefTest {
 
     @Before
     public void setUp() throws Exception {
-        def = new IndexDef("index1", false, Lists.newArrayList("col1"), 
IndexDef.IndexType.BITMAP, "balabala");
+        def = new IndexDef("index1", false, Lists.newArrayList("col1"), 
IndexDef.IndexType.BITMAP, null, "balabala");
     }
 
     @Test
@@ -46,7 +46,7 @@ public class IndexDefTest {
                             + 
"x1xxxxxxxxxxxxxxxxxindex1xxxxxxxxxxxxxxxxxindex1xxxxxxxxxxxxxxxxxindex1xxxxxxxxxxxxx"
                             + 
"xxxxindex1xxxxxxxxxxxxxxxxxindex1xxxxxxxxxxxxxxxxxindex1xxxxxxxxxxxxxxxxxindex1xxxxx"
                             + "xxxxxxxxxxxxindex1xxxxxxxxxxxxxxxxx", false,
-                    Lists.newArrayList("col1"), IndexDef.IndexType.BITMAP,
+                    Lists.newArrayList("col1"), IndexDef.IndexType.BITMAP, 
null,
                     "balabala");
             def.analyze();
             Assert.fail("No exception throws.");
@@ -54,7 +54,7 @@ public class IndexDefTest {
             Assert.assertTrue(e instanceof AnalysisException);
         }
         try {
-            def = new IndexDef("", false, Lists.newArrayList("col1"), 
IndexDef.IndexType.BITMAP, "balabala");
+            def = new IndexDef("", false, Lists.newArrayList("col1"), 
IndexDef.IndexType.BITMAP, null, "balabala");
             def.analyze();
             Assert.fail("No exception throws.");
         } catch (AnalysisException e) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java
index 871389d6dd..f547189ff1 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java
@@ -56,8 +56,8 @@ public class OlapTableTest {
                 continue;
             }
             OlapTable tbl = (OlapTable) table;
-            tbl.setIndexes(Lists.newArrayList(new Index("index", 
Lists.newArrayList("col"),
-                    IndexDef.IndexType.BITMAP, "xxxxxx")));
+            tbl.setIndexes(Lists.newArrayList(new Index(0, "index", 
Lists.newArrayList("col"),
+                    IndexDef.IndexType.BITMAP, null, "xxxxxx")));
             System.out.println("orig table id: " + tbl.getId());
 
             FastByteArrayOutputStream byteArrayOutputStream = new 
FastByteArrayOutputStream();
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/persist/TableAddOrDropColumnsInfoTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/persist/TableAddOrDropColumnsInfoTest.java
index a97dd27bf9..e849198a5b 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/persist/TableAddOrDropColumnsInfoTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/persist/TableAddOrDropColumnsInfoTest.java
@@ -65,7 +65,7 @@ public class TableAddOrDropColumnsInfoTest {
         indexSchemaMap.put(tableId, fullSchema);
 
         List<Index> indexes = Lists.newArrayList(
-                new Index("index", Lists.newArrayList("testCol1"), 
IndexDef.IndexType.BITMAP, "xxxxxx"));
+                new Index(0, "index", Lists.newArrayList("testCol1"), 
IndexDef.IndexType.BITMAP, null, "xxxxxx"));
 
         TableAddOrDropColumnsInfo tableAddOrDropColumnsInfo1 = new 
TableAddOrDropColumnsInfo(dbId, tableId,
                 indexSchemaMap, indexes, jobId);
diff --git a/gensrc/proto/olap_file.proto b/gensrc/proto/olap_file.proto
index f19228b935..30b127fc78 100644
--- a/gensrc/proto/olap_file.proto
+++ b/gensrc/proto/olap_file.proto
@@ -201,6 +201,20 @@ message ColumnPB {
     repeated string children_column_names = 18;
 }
 
+enum IndexType {
+    BITMAP = 0;
+    INVERTED = 1;
+    BLOOMFILTER = 2;
+}
+
+message TabletIndexPB {
+    optional int64 index_id = 1;
+    optional string index_name = 2;
+    optional IndexType index_type = 3;
+    repeated int32 col_unique_id = 4;
+    map<string, string> properties = 5;
+}
+
 enum SortType {
     LEXICAL = 0;
     ZORDER  = 1;
@@ -222,6 +236,7 @@ message TabletSchemaPB {
     optional segment_v2.CompressionTypePB compression_type = 13 [default=LZ4F];
     optional int32 schema_version = 14;
     optional bool disable_auto_compaction = 15 [default=false];
+    repeated TabletIndexPB index = 16;
 }
 
 enum TabletStatePB {
diff --git a/gensrc/thrift/Descriptors.thrift b/gensrc/thrift/Descriptors.thrift
index a3fc84571b..d133b3a27d 100644
--- a/gensrc/thrift/Descriptors.thrift
+++ b/gensrc/thrift/Descriptors.thrift
@@ -118,7 +118,9 @@ enum THdfsCompression {
 }
 
 enum TIndexType {
-  BITMAP
+  BITMAP,
+  INVERTED,
+  BLOOMFILTER
 }
 
 // Mapping from names defined by Avro to the enum.
@@ -195,6 +197,8 @@ struct TOlapTableIndex {
   2: optional list<string> columns
   3: optional TIndexType index_type
   4: optional string comment
+  5: optional i64 index_id
+  6: optional map<string, string> properties
 }
 
 struct TTabletLocation {
diff --git a/regression-test/data/index_p0/test_bitmap_index.out 
b/regression-test/data/index_p0/test_bitmap_index.out
index 3b37588e29..ff0754c309 100644
--- a/regression-test/data/index_p0/test_bitmap_index.out
+++ b/regression-test/data/index_p0/test_bitmap_index.out
@@ -17,21 +17,21 @@ k14 DATETIMEV2(3)   Yes     false   \N      NONE
 k15    DATETIMEV2(6)   Yes     false   \N      NONE
 
 -- !sql --
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index1  
        k1                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index2  
        k2                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index3  
        k3                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index4  
        k4                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index5  
        k5                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index6  
        k6                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index7  
        k7                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index8  
        k8                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index9  
        k9                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index10 
        k10                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index11 
        k11                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index12 
        k12                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index13 
        k13                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index14 
        k14                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_dup         index15 
        k15                                             BITMAP  
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index1  
        k1                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index2  
        k2                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index3  
        k3                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index4  
        k4                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index5  
        k5                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index6  
        k6                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index7  
        k7                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index8  
        k8                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index9  
        k9                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index10 
        k10                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index11 
        k11                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index12 
        k12                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index13 
        k13                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index14 
        k14                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_dup         index15 
        k15                                             BITMAP          
 
 -- !sql --
 1      1       1       1       1       1       2022-05-31      
2022-05-31T10:00        1       1       true    2022-05-31      
2022-05-31T10:00        2022-05-31T10:00:00.111 2022-05-31T10:00:00.111111
@@ -55,21 +55,21 @@ k15 DATETIMEV2(6)   Yes     true    \N
 v1     INT     Yes     false   \N      SUM
 
 -- !sql --
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index1  
        k1                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index2  
        k2                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index3  
        k3                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index4  
        k4                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index5  
        k5                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index6  
        k6                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index7  
        k7                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index8  
        k8                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index9  
        k9                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index10 
        k10                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index11 
        k11                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index12 
        k12                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index13 
        k13                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index14 
        k14                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_agg         index15 
        k15                                             BITMAP  
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index1  
        k1                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index2  
        k2                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index3  
        k3                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index4  
        k4                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index5  
        k5                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index6  
        k6                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index7  
        k7                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index8  
        k8                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index9  
        k9                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index10 
        k10                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index11 
        k11                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index12 
        k12                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index13 
        k13                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index14 
        k14                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_agg         index15 
        k15                                             BITMAP          
 
 -- !sql --
 1      1       1       1       1       1       2022-05-31      
2022-05-31T10:00        1       1       true    2022-05-31      
2022-05-31T10:00        2022-05-31T10:00:00.111 2022-05-31T10:00:00.111111      
1
@@ -93,22 +93,22 @@ k15 DATETIMEV2(6)   Yes     false   \N      REPLACE
 v1     INT     Yes     false   \N      REPLACE
 
 -- !sql --
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index1          k1                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index2          k2                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index3          k3                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index4          k4                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index5          k5                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index6          k6                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index7          k7                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index8          k8                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index9          k9                                              BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index10         k10                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index11         k11                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index12         k12                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index13         k13                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index14         k14                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index15         k15                                             BITMAP  
-default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index16         v1                                              BITMAP  
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index1          k1                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index2          k2                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index3          k3                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index4          k4                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index5          k5                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index6          k6                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index7          k7                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index8          k8                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index9          k9                                              BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index10         k10                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index11         k11                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index12         k12                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index13         k13                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index14         k14                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index15         k15                                             BITMAP          
+default_cluster:regression_test_index_p0.test_bitmap_index_unique              
index16         v1                                              BITMAP          
 
 -- !sql --
 1      1       1       1       1       1       2022-05-31      
2022-05-31T10:00        1       1       true    2022-05-31      
2022-05-31T10:00        2022-05-31T10:00:00.111 2022-05-31T10:00:00.111111      
1
diff --git 
a/regression-test/data/index_p0/test_decimal_bitmap_index_multi_page.out 
b/regression-test/data/index_p0/test_decimal_bitmap_index_multi_page.out
index 538cbb9404..49b5a9da49 100644
--- a/regression-test/data/index_p0/test_decimal_bitmap_index_multi_page.out
+++ b/regression-test/data/index_p0/test_decimal_bitmap_index_multi_page.out
@@ -3,7 +3,7 @@
 a      DECIMAL(12,6)   No      true    \N      
 
 -- !sql --
-default_cluster:regression_test_index_p0.test_decimal_bitmap_index_multi_page  
        bitmap_index_multi_page         a                                       
        BITMAP  
+default_cluster:regression_test_index_p0.test_decimal_bitmap_index_multi_page  
        bitmap_index_multi_page         a                                       
        BITMAP          
 
 -- !sql --
 0.000001
diff --git a/regression-test/suites/index_p0/test_index_meta.groovy 
b/regression-test/suites/index_p0/test_index_meta.groovy
new file mode 100644
index 0000000000..f31c125220
--- /dev/null
+++ b/regression-test/suites/index_p0/test_index_meta.groovy
@@ -0,0 +1,167 @@
+// 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 groovy.json.JsonOutput
+import org.codehaus.groovy.runtime.IOGroovyMethods
+
+suite("index_meta", "p0") {
+    // prepare test table
+    def timeout = 60000
+    def delta_time = 1000
+    def alter_res = "null"
+    def useTime = 0
+    def wait_for_latest_op_on_table_finish = { table_name, OpTimeout ->
+        for(int t = delta_time; t <= OpTimeout; t += delta_time){
+            alter_res = sql """SHOW ALTER TABLE COLUMN WHERE TableName = 
"${table_name}" ORDER BY CreateTime DESC LIMIT 1;"""
+            alter_res = alter_res.toString()
+            if(alter_res.contains("FINISHED")) {
+                 break
+            }
+            useTime = t
+            sleep(delta_time)
+        }
+        assertTrue(useTime <= OpTimeout)
+    }
+
+    def tableName = "test_index_meta"
+
+    sql "DROP TABLE IF EXISTS ${tableName}"
+    // create 1 replica table
+    sql """
+            CREATE TABLE IF NOT EXISTS ${tableName} (
+                `id` INT NULL,
+                `name` STRING NULL,
+                `description` STRING NULL,
+                INDEX idx_id (`id`) USING BITMAP COMMENT 'index for id',
+                INDEX idx_name (`name`) USING INVERTED 
PROPERTIES("parser"="none") COMMENT 'index for name'
+            )
+            DUPLICATE KEY(`id`)
+            DISTRIBUTED BY HASH(`id`) BUCKETS 1
+            properties("replication_num" = "1");
+    """
+
+    // set enable_vectorized_engine=true
+    sql """ SET enable_vectorized_engine=true; """
+    def var_result = sql "show variables"
+    logger.info("show variales result: " + var_result )
+
+    // show index of create table
+    def show_result = sql "show index from ${tableName}"
+    logger.info("show index from " + tableName + " result: " + show_result)
+    assertEquals(show_result.size(), 2)
+    assertEquals(show_result[0][2], "idx_id")
+    assertEquals(show_result[0][4], "id")
+    assertEquals(show_result[0][10], "BITMAP")
+    assertEquals(show_result[0][11], "index for id")
+    assertEquals(show_result[0][12], "")
+    assertEquals(show_result[1][2], "idx_name")
+    assertEquals(show_result[1][4], "name")
+    assertEquals(show_result[1][10], "INVERTED")
+    assertEquals(show_result[1][11], "index for name")
+    assertEquals(show_result[1][12], "(\"parser\" = \"none\")")
+
+    // add index on column description
+    sql "create index idx_desc on ${tableName}(description) USING INVERTED 
PROPERTIES(\"parser\"=\"standard\") COMMENT 'index for description';"
+    wait_for_latest_op_on_table_finish(tableName, timeout)
+
+    // show index after add index
+    show_result = sql "show index from ${tableName}"
+    logger.info("show index from " + tableName + " result: " + show_result)
+    assertEquals(show_result.size(), 3)
+    assertEquals(show_result[0][2], "idx_id")
+    assertEquals(show_result[0][4], "id")
+    assertEquals(show_result[0][10], "BITMAP")
+    assertEquals(show_result[0][11], "index for id")
+    assertEquals(show_result[0][12], "")
+    assertEquals(show_result[1][2], "idx_name")
+    assertEquals(show_result[1][4], "name")
+    assertEquals(show_result[1][10], "INVERTED")
+    assertEquals(show_result[1][11], "index for name")
+    assertEquals(show_result[1][12], "(\"parser\" = \"none\")")
+    assertEquals(show_result[2][2], "idx_desc")
+    assertEquals(show_result[2][4], "description")
+    assertEquals(show_result[2][10], "INVERTED")
+    assertEquals(show_result[2][11], "index for description")
+    assertEquals(show_result[2][12], "(\"parser\" = \"standard\")")
+
+    // drop index
+    // add index on column description
+    sql "drop index idx_name on ${tableName}"
+    wait_for_latest_op_on_table_finish(tableName, timeout)
+
+    show_result = sql "show index from ${tableName}"
+    logger.info("show index from " + tableName + " result: " + show_result)
+    assertEquals(show_result.size(), 2)
+    assertEquals(show_result[0][2], "idx_id")
+    assertEquals(show_result[0][4], "id")
+    assertEquals(show_result[0][10], "BITMAP")
+    assertEquals(show_result[0][11], "index for id")
+    assertEquals(show_result[0][12], "")
+    assertEquals(show_result[1][2], "idx_desc")
+    assertEquals(show_result[1][4], "description")
+    assertEquals(show_result[1][10], "INVERTED")
+    assertEquals(show_result[1][11], "index for description")
+    assertEquals(show_result[1][12], "(\"parser\" = \"standard\")")
+
+    // add index on column description
+    sql "create index idx_name on ${tableName}(name) USING INVERTED COMMENT 
'new index for name';"
+    wait_for_latest_op_on_table_finish(tableName, timeout)
+
+    // show index after add index
+    show_result = sql "show index from ${tableName}"
+    logger.info("show index from " + tableName + " result: " + show_result)
+    assertEquals(show_result.size(), 3)
+    assertEquals(show_result[0][2], "idx_id")
+    assertEquals(show_result[0][4], "id")
+    assertEquals(show_result[0][10], "BITMAP")
+    assertEquals(show_result[0][11], "index for id")
+    assertEquals(show_result[0][12], "")
+    assertEquals(show_result[1][2], "idx_desc")
+    assertEquals(show_result[1][4], "description")
+    assertEquals(show_result[1][10], "INVERTED")
+    assertEquals(show_result[1][11], "index for description")
+    assertEquals(show_result[1][12], "(\"parser\" = \"standard\")")
+    assertEquals(show_result[2][2], "idx_name")
+    assertEquals(show_result[2][4], "name")
+    assertEquals(show_result[2][10], "INVERTED")
+    assertEquals(show_result[2][11], "new index for name")
+    assertEquals(show_result[2][12], "")
+
+
+    def show_tablets_result = sql "show tablets from ${tableName}"
+    logger.info("show tablets from " + tableName + " result: " + 
show_tablets_result)
+    for (j in range(0, show_tablets_result.size())) {
+        String metaUrl = show_tablets_result[j][16]
+        String getMetaCommand = "curl -X GET " + metaUrl
+        def process = getMetaCommand.toString().execute()
+        int code = process.waitFor()
+        String err = IOGroovyMethods.getText(new BufferedReader(new 
InputStreamReader(process.getErrorStream())));
+        String out = process.getText()
+        logger.info("get meta process result: code=" + code + ", out=" + out + 
", err=" + err)
+        assertEquals(code, 0)
+        def json = parseJson(out.trim())
+        assert json.schema.index instanceof List
+        int i = 0;
+        for (Object index in (List) json.schema.index) {
+            // assertEquals(index.index_id, i);
+            assertEquals(index.index_name, show_result[i][2])
+            assertEquals(index.index_type, show_result[i][10])
+            // assertEquals(index.properties, show_result[j][12]);
+            i++;
+        }
+    }
+}


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

Reply via email to