This is an automated email from the ASF dual-hosted git repository. hellostephen 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 47ffca97696 [enhancement](inverted index) ensure consistent ordering of properties for inverted index show (#51467) 47ffca97696 is described below commit 47ffca97696aff67cfcfcd961c4933e4699fff29 Author: airborne12 <jiang...@selectdb.com> AuthorDate: Thu Jun 5 14:40:07 2025 +0800 [enhancement](inverted index) ensure consistent ordering of properties for inverted index show (#51467) Problem Summary: This PR enhances the inverted index implementation to always output its properties in a consistent, alphabetical order and adds tests to verify this behavior. --- .../main/java/org/apache/doris/catalog/Index.java | 3 +- .../doris/analysis/ShowCreateTableStmtTest.java | 39 +++++++++++ .../doris/catalog/IndexPropertiesOrderTest.java | 78 ++++++++++++++++++++++ .../doris/common/proc/IndexesProcNodeTest.java | 2 +- .../test_backup_restore_inverted_index.groovy | 2 +- .../suites/index_p0/test_index_meta.groovy | 10 +-- 6 files changed, 126 insertions(+), 8 deletions(-) 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 af4ff1501d6..d55aedb97af 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 @@ -145,7 +145,8 @@ public class Index implements Writable { return ""; } - return "(" + new PrintableMap(properties, "=", true, false, ",").toString() + ")"; + // Use TreeMap to ensure consistent ordering of properties + return "(" + new PrintableMap(new java.util.TreeMap<>(properties), "=", true, false, ",").toString() + ")"; } public String getInvertedIndexParser() { diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateTableStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateTableStmtTest.java index 0faf4a8f34e..7294398ea4c 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateTableStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateTableStmtTest.java @@ -40,6 +40,15 @@ public class ShowCreateTableStmtTest extends TestWithFeService { + ") " + "distributed by hash(k1) buckets 1\n" + "properties(\"replication_num\" = \"1\");"); + + // Create a table with inverted index for testing index properties order + createTable("create table table_with_index\n" + + "(id int, name varchar(100), description text, " + + "INDEX index_name(name) USING INVERTED PROPERTIES(\"parser\"=\"english\", \"lower_case\"=\"true\", \"support_phrase\"=\"true\") COMMENT 'name index', " + + "INDEX index_description(description) USING INVERTED PROPERTIES(\"support_phrase\"=\"true\", \"parser\"=\"standard\", \"lower_case\"=\"true\") COMMENT 'description index') " + + "DUPLICATE KEY(id) " + + "distributed by hash(id) buckets 1\n" + + "properties(\"replication_num\" = \"1\");"); } @@ -70,4 +79,34 @@ public class ShowCreateTableStmtTest extends TestWithFeService { Assertions.assertTrue(!showSql.contains("PARTITION BY")); Assertions.assertTrue(!showSql.contains("PARTITION `p01`")); } + + @Test + public void testIndexPropertiesOrder() throws Exception { + String sql = "show create table table_with_index"; + + // Execute the same query multiple times to check consistency + ShowResultSet showResultSet1 = showCreateTable(sql); + ShowResultSet showResultSet2 = showCreateTable(sql); + ShowResultSet showResultSet3 = showCreateTable(sql); + + String showSql1 = showResultSet1.getResultRows().get(0).get(1); + String showSql2 = showResultSet2.getResultRows().get(0).get(1); + String showSql3 = showResultSet3.getResultRows().get(0).get(1); + + // All show create table results should be identical + Assertions.assertEquals(showSql1, showSql2, "Show create table results should be consistent across multiple executions"); + Assertions.assertEquals(showSql2, showSql3, "Show create table results should be consistent across multiple executions"); + + // Verify that the index properties are present and in alphabetical order + // The properties should appear as: "lower_case" = "true", "parser" = "english", "support_phrase" = "true" + Assertions.assertTrue(showSql1.contains("INDEX index_name (`name`) USING INVERTED " + + "PROPERTIES(\"lower_case\" = \"true\", \"parser\" = \"english\", " + + "\"support_phrase\" = \"true\")"), + "Index properties should be in alphabetical order"); + Assertions.assertTrue(showSql1.contains( + "INDEX index_description (`description`) USING INVERTED " + + "PROPERTIES(\"lower_case\" = \"true\", \"parser\" = \"standard\", " + + "\"support_phrase\" = \"true\")"), + "Index properties should be in alphabetical order"); + } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/IndexPropertiesOrderTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/IndexPropertiesOrderTest.java new file mode 100644 index 00000000000..19ba0486e26 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/IndexPropertiesOrderTest.java @@ -0,0 +1,78 @@ +// 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.catalog; + +import org.apache.doris.analysis.IndexDef; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class IndexPropertiesOrderTest { + + @Test + public void testIndexPropertiesConsistentOrder() { + // Create properties with multiple key-value pairs to test ordering + Map<String, String> properties = new HashMap<>(); + properties.put("parser", "english"); + properties.put("lower_case", "true"); + properties.put("support_phrase", "true"); + + List<String> columns = Arrays.asList("description"); + + // Create multiple Index objects with the same properties + Index index1 = new Index(1L, "test_idx", columns, IndexDef.IndexType.INVERTED, + new HashMap<>(properties), "test comment"); + Index index2 = new Index(2L, "test_idx", columns, IndexDef.IndexType.INVERTED, + new HashMap<>(properties), "test comment"); + Index index3 = new Index(3L, "test_idx", columns, IndexDef.IndexType.INVERTED, + new HashMap<>(properties), "test comment"); + + // The properties part should be consistent across all instances + String props1 = index1.getPropertiesString(); + String props2 = index2.getPropertiesString(); + String props3 = index3.getPropertiesString(); + + // Assert that all properties strings are identical + Assertions.assertEquals(props1, props2, "Properties order should be consistent between index1 and index2"); + Assertions.assertEquals(props2, props3, "Properties order should be consistent between index2 and index3"); + Assertions.assertEquals(props1, props3, "Properties order should be consistent between index1 and index3"); + + // Verify the properties are in alphabetical order + Assertions.assertTrue(props1.contains("lower_case"), "Properties should contain lower_case"); + Assertions.assertTrue(props1.contains("parser"), "Properties should contain parser"); + Assertions.assertTrue(props1.contains("support_phrase"), "Properties should contain support_phrase"); + + // Test with different orderings of the same properties + Map<String, String> properties2 = new LinkedHashMap<>(); + properties2.put("support_phrase", "true"); + properties2.put("parser", "english"); + properties2.put("lower_case", "true"); + Index index4 = new Index(4L, "test_idx", columns, IndexDef.IndexType.INVERTED, + properties2, "test comment"); + String props4 = index4.getPropertiesString(); + + // Should still be the same as the others due to TreeMap sorting + Assertions.assertEquals(props1, props4, "Properties order should be consistent regardless of input order"); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java b/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java index 6cae36af9f2..48ff245af5c 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java @@ -80,7 +80,7 @@ public class IndexesProcNodeTest { Assert.assertEquals(procResult.getRows().get(1).get(5), "col_2"); Assert.assertEquals(procResult.getRows().get(1).get(11), "INVERTED"); Assert.assertEquals(procResult.getRows().get(1).get(12), "inverted index on col_2"); - Assert.assertEquals(procResult.getRows().get(1).get(13), "(\"parser\" = \"unicode\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")"); + Assert.assertEquals(procResult.getRows().get(1).get(13), "(\"lower_case\" = \"true\", \"parser\" = \"unicode\", \"support_phrase\" = \"true\")"); Assert.assertEquals(procResult.getRows().get(2).get(0), "tbl_test_indexes_proc"); Assert.assertEquals(procResult.getRows().get(2).get(1), "3"); diff --git a/regression-test/suites/backup_restore/test_backup_restore_inverted_index.groovy b/regression-test/suites/backup_restore/test_backup_restore_inverted_index.groovy index 6e3ad67c3c1..443c0e80547 100644 --- a/regression-test/suites/backup_restore/test_backup_restore_inverted_index.groovy +++ b/regression-test/suites/backup_restore/test_backup_restore_inverted_index.groovy @@ -75,7 +75,7 @@ suite("test_backup_restore_inverted_index", "backup_restore") { def restore_index_comment = sql "SHOW CREATE TABLE ${dbName}.${tableName}" - assertTrue(restore_index_comment[0][1].contains("USING INVERTED PROPERTIES(\"parser\" = \"english\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")")) + assertTrue(restore_index_comment[0][1].contains("USING INVERTED PROPERTIES(\"lower_case\" = \"true\", \"parser\" = \"english\", \"support_phrase\" = \"true\")")) result = sql "SELECT id, TOKENIZE(comment,'\"parser\"=\"english\"') as token FROM ${dbName}.${tableName}" assertEquals(result.size(), 2) diff --git a/regression-test/suites/index_p0/test_index_meta.groovy b/regression-test/suites/index_p0/test_index_meta.groovy index b38206e7e21..d7647f2a9a3 100644 --- a/regression-test/suites/index_p0/test_index_meta.groovy +++ b/regression-test/suites/index_p0/test_index_meta.groovy @@ -71,7 +71,7 @@ suite("index_meta", "p0") { 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\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")") + assertEquals(show_result[1][12], "(\"lower_case\" = \"true\", \"parser\" = \"none\", \"support_phrase\" = \"true\")") // add index on column description sql "create index idx_desc on ${tableName}(description) USING INVERTED PROPERTIES(\"parser\"=\"standard\") COMMENT 'index for description';" @@ -90,12 +90,12 @@ suite("index_meta", "p0") { 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\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")") + assertEquals(show_result[1][12], "(\"lower_case\" = \"true\", \"parser\" = \"none\", \"support_phrase\" = \"true\")") 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\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")") + assertEquals(show_result[2][12], "(\"lower_case\" = \"true\", \"parser\" = \"standard\", \"support_phrase\" = \"true\")") // drop index // add index on column description @@ -114,7 +114,7 @@ suite("index_meta", "p0") { 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\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")") + assertEquals(show_result[1][12], "(\"lower_case\" = \"true\", \"parser\" = \"standard\", \"support_phrase\" = \"true\")") // add index on column description sql "create index idx_name on ${tableName}(name) USING INVERTED COMMENT 'new index for name';" @@ -133,7 +133,7 @@ suite("index_meta", "p0") { 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\", \"lower_case\" = \"true\", \"support_phrase\" = \"true\")") + assertEquals(show_result[1][12], "(\"lower_case\" = \"true\", \"parser\" = \"standard\", \"support_phrase\" = \"true\")") assertEquals(show_result[2][2], "idx_name") assertEquals(show_result[2][4], "name") assertEquals(show_result[2][10], "INVERTED") --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org