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

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 730a62d32ea support save unique key in metadata for mysql (#27611)
730a62d32ea is described below

commit 730a62d32ea2e86a888f747a8c7619df5bb35dda
Author: Chuxin Chen <[email protected]>
AuthorDate: Wed Aug 2 14:51:09 2023 +0800

    support save unique key in metadata for mysql (#27611)
    
    * support save unique key in metadata for mysql
    
    * support save unique key in metadata for mysql
    
    * support save unique key in metadata for mysql
    
    * support save unique key in metadata for mysql
    
    * support save unique key in metadata for mysql
    
    * support save unique key in metadata for mysql
---
 .../reviser/EncryptMetaDataReviseEntry.java        |  6 +++
 .../reviser/index/EncryptIndexReviser.java         | 58 ++++++++++++++++++++++
 .../shardingsphere/encrypt/rule/EncryptTable.java  | 16 ++++++
 .../reviser/index/ShardingIndexReviser.java        |  7 ++-
 .../schema/builder/GenericSchemaBuilder.java       |  5 +-
 .../database/schema/model/ShardingSphereIndex.java |  9 ++++
 .../yaml/schema/pojo/YamlShardingSphereIndex.java  |  7 +++
 .../yaml/schema/swapper/YamlTableSwapper.java      |  7 ++-
 .../core/metadata/data/loader/MetaDataLoader.java  |  2 +-
 .../data/loader/type/IndexMetaDataLoader.java      | 19 +++++--
 .../core/metadata/data/model/IndexMetaData.java    |  9 ++++
 .../metadata/data/loader/MySQLMetaDataLoader.java  | 25 +++++++---
 .../data/loader/MySQLMetaDataLoaderTest.java       | 15 ++++--
 .../metadata/reviser/index/SingleIndexReviser.java |  7 ++-
 .../data/actual/init-sql/mysql/01-actual-init.sql  |  2 +-
 .../expected/init-sql/mysql/01-expected-init.sql   |  2 +-
 16 files changed, 171 insertions(+), 25 deletions(-)

diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/EncryptMetaDataReviseEntry.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/EncryptMetaDataReviseEntry.java
index eaf4847a706..66f05ff20c5 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/EncryptMetaDataReviseEntry.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/EncryptMetaDataReviseEntry.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.encrypt.metadata.reviser;
 import org.apache.shardingsphere.encrypt.constant.EncryptOrder;
 import 
org.apache.shardingsphere.encrypt.metadata.reviser.column.EncryptColumnExistedReviser;
 import 
org.apache.shardingsphere.encrypt.metadata.reviser.column.EncryptColumnNameReviser;
+import 
org.apache.shardingsphere.encrypt.metadata.reviser.index.EncryptIndexReviser;
 import org.apache.shardingsphere.encrypt.rule.EncryptRule;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.reviser.MetaDataReviseEntry;
 
@@ -40,6 +41,11 @@ public final class EncryptMetaDataReviseEntry implements 
MetaDataReviseEntry<Enc
         return 
rule.findEncryptTable(tableName).map(EncryptColumnNameReviser::new);
     }
     
+    @Override
+    public Optional<EncryptIndexReviser> getIndexReviser(final EncryptRule 
rule, final String tableName) {
+        return rule.findEncryptTable(tableName).map(EncryptIndexReviser::new);
+    }
+    
     @Override
     public int getOrder() {
         return EncryptOrder.ORDER;
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/index/EncryptIndexReviser.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/index/EncryptIndexReviser.java
new file mode 100644
index 00000000000..5aabd18dafb
--- /dev/null
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/reviser/index/EncryptIndexReviser.java
@@ -0,0 +1,58 @@
+/*
+ * 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.shardingsphere.encrypt.metadata.reviser.index;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.encrypt.rule.EncryptRule;
+import org.apache.shardingsphere.encrypt.rule.EncryptTable;
+import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.IndexMetaData;
+import 
org.apache.shardingsphere.infra.metadata.database.schema.reviser.index.IndexReviser;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Optional;
+
+/**
+ * Encrypt index reviser.
+ */
+@RequiredArgsConstructor
+public final class EncryptIndexReviser implements IndexReviser<EncryptRule> {
+    
+    private final EncryptTable encryptTable;
+    
+    @Override
+    public Optional<IndexMetaData> revise(final String tableName, final 
IndexMetaData originalMetaData, final EncryptRule rule) {
+        if (originalMetaData.getColumns().isEmpty()) {
+            return Optional.empty();
+        }
+        Collection<String> columns = new LinkedHashSet<>();
+        for (String each : originalMetaData.getColumns()) {
+            if (encryptTable.isCipherColumn(each)) {
+                columns.add(encryptTable.getLogicColumnByCipherColumn(each));
+            } else if (encryptTable.isAssistedQueryColumn(each)) {
+                
columns.add(encryptTable.getLogicColumnByAssistedQueryColumn(each));
+            } else {
+                columns.add(each);
+            }
+        }
+        IndexMetaData result = new IndexMetaData(originalMetaData.getName());
+        result.getColumns().addAll(columns);
+        result.setUnique(originalMetaData.isUnique());
+        return Optional.of(result);
+    }
+}
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptTable.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptTable.java
index b49ed5be327..073718b5a74 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptTable.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptTable.java
@@ -143,6 +143,22 @@ public final class EncryptTable {
         throw new EncryptLogicColumnNotFoundException(cipherColumnName);
     }
     
+    /**
+     * Get logic column by assisted query column.
+     *
+     * @param assistQueryColumnName assisted query column name
+     * @return logic column name
+     * @throws EncryptLogicColumnNotFoundException encrypt logic column not 
found exception
+     */
+    public String getLogicColumnByAssistedQueryColumn(final String 
assistQueryColumnName) {
+        for (Entry<String, EncryptColumn> entry : columns.entrySet()) {
+            if (entry.getValue().getAssistedQuery().isPresent() && 
entry.getValue().getAssistedQuery().get().getName().equalsIgnoreCase(assistQueryColumnName))
 {
+                return entry.getKey();
+            }
+        }
+        throw new EncryptLogicColumnNotFoundException(assistQueryColumnName);
+    }
+    
     /**
      * Is assisted query column or not.
      *
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/reviser/index/ShardingIndexReviser.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/reviser/index/ShardingIndexReviser.java
index 9b33e3aea79..86e9c2941e7 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/reviser/index/ShardingIndexReviser.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/reviser/index/ShardingIndexReviser.java
@@ -18,9 +18,9 @@
 package org.apache.shardingsphere.sharding.metadata.reviser.index;
 
 import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.IndexMetaData;
 import org.apache.shardingsphere.infra.datanode.DataNode;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.reviser.index.IndexReviser;
-import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.IndexMetaData;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
 import org.apache.shardingsphere.sharding.rule.TableRule;
 
@@ -39,7 +39,10 @@ public final class ShardingIndexReviser implements 
IndexReviser<ShardingRule> {
         for (DataNode each : tableRule.getActualDataNodes()) {
             Optional<String> logicIndexName = 
getLogicIndex(originalMetaData.getName(), each.getTableName());
             if (logicIndexName.isPresent()) {
-                return Optional.of(new IndexMetaData(logicIndexName.get()));
+                IndexMetaData result = new IndexMetaData(logicIndexName.get());
+                result.getColumns().addAll(originalMetaData.getColumns());
+                result.setUnique(originalMetaData.isUnique());
+                return Optional.of(result);
             }
         }
         return Optional.empty();
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
index 02acc209b52..d1535d41de6 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
@@ -157,7 +157,10 @@ public final class GenericSchemaBuilder {
     private static Collection<ShardingSphereIndex> convertToIndexes(final 
Collection<IndexMetaData> indexMetaDataList) {
         Collection<ShardingSphereIndex> result = new LinkedList<>();
         for (IndexMetaData each : indexMetaDataList) {
-            result.add(new ShardingSphereIndex(each.getName()));
+            ShardingSphereIndex index = new 
ShardingSphereIndex(each.getName());
+            index.getColumns().addAll(each.getColumns());
+            index.setUnique(each.isUnique());
+            result.add(index);
         }
         return result;
     }
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereIndex.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereIndex.java
index cac96eec1f8..0ffee4f4200 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereIndex.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereIndex.java
@@ -20,8 +20,12 @@ package 
org.apache.shardingsphere.infra.metadata.database.schema.model;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import lombok.ToString;
 
+import java.util.Collection;
+import java.util.LinkedList;
+
 /**
  * ShardingSphere index.
  */
@@ -32,4 +36,9 @@ import lombok.ToString;
 public final class ShardingSphereIndex {
     
     private final String name;
+    
+    private final Collection<String> columns = new LinkedList<>();
+    
+    @Setter
+    private boolean unique;
 }
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/pojo/YamlShardingSphereIndex.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/pojo/YamlShardingSphereIndex.java
index b6f08dd9902..a78bca448c9 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/pojo/YamlShardingSphereIndex.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/pojo/YamlShardingSphereIndex.java
@@ -21,6 +21,9 @@ import lombok.Getter;
 import lombok.Setter;
 import org.apache.shardingsphere.infra.util.yaml.YamlConfiguration;
 
+import java.util.Collection;
+import java.util.LinkedList;
+
 /**
  * ShardingSphere index meta data for YAML.
  */
@@ -29,4 +32,8 @@ import 
org.apache.shardingsphere.infra.util.yaml.YamlConfiguration;
 public final class YamlShardingSphereIndex implements YamlConfiguration {
     
     private String name;
+    
+    private Collection<String> columns = new LinkedList<>();
+    
+    private boolean unique;
 }
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/swapper/YamlTableSwapper.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/swapper/YamlTableSwapper.java
index f0d73e16359..2da8e8e5a83 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/swapper/YamlTableSwapper.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/yaml/schema/swapper/YamlTableSwapper.java
@@ -66,7 +66,10 @@ public final class YamlTableSwapper implements 
YamlConfigurationSwapper<YamlShar
     }
     
     private ShardingSphereIndex swapIndex(final YamlShardingSphereIndex index) 
{
-        return new ShardingSphereIndex(index.getName());
+        ShardingSphereIndex result = new ShardingSphereIndex(index.getName());
+        result.getColumns().addAll(index.getColumns());
+        result.setUnique(index.isUnique());
+        return result;
     }
     
     private Collection<ShardingSphereColumn> swapColumns(final Map<String, 
YamlShardingSphereColumn> indexes) {
@@ -95,6 +98,8 @@ public final class YamlTableSwapper implements 
YamlConfigurationSwapper<YamlShar
     private YamlShardingSphereIndex swapYamlIndex(final ShardingSphereIndex 
index) {
         YamlShardingSphereIndex result = new YamlShardingSphereIndex();
         result.setName(index.getName());
+        result.getColumns().addAll(index.getColumns());
+        result.setUnique(index.isUnique());
         return result;
     }
     
diff --git 
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/MetaDataLoader.java
 
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/MetaDataLoader.java
index cd4e6781ffa..f51cac2a0a3 100644
--- 
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/MetaDataLoader.java
+++ 
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/MetaDataLoader.java
@@ -21,8 +21,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.SchemaMetaData;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.loader.type.TableMetaDataLoader;
+import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.SchemaMetaData;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.TableMetaData;
 import 
org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
 import 
org.apache.shardingsphere.infra.exception.core.external.sql.type.generic.UnknownSQLException;
diff --git 
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/type/IndexMetaDataLoader.java
 
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/type/IndexMetaDataLoader.java
index 41db803a484..7ea004a1d80 100644
--- 
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/type/IndexMetaDataLoader.java
+++ 
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/loader/type/IndexMetaDataLoader.java
@@ -25,7 +25,8 @@ import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Index meta data loader.
@@ -48,12 +49,20 @@ public final class IndexMetaDataLoader {
      */
     @SuppressWarnings("CollectionWithoutInitialCapacity")
     public static Collection<IndexMetaData> load(final Connection connection, 
final String table) throws SQLException {
-        Collection<IndexMetaData> result = new HashSet<>();
+        Map<String, IndexMetaData> result = new HashMap<>();
         try (ResultSet resultSet = 
connection.getMetaData().getIndexInfo(connection.getCatalog(), 
connection.getSchema(), table, false, false)) {
             while (resultSet.next()) {
                 String indexName = resultSet.getString(INDEX_NAME);
-                if (null != indexName) {
-                    result.add(new IndexMetaData(indexName));
+                if (null == indexName) {
+                    continue;
+                }
+                if (!result.containsKey(indexName)) {
+                    IndexMetaData indexMetaData = new IndexMetaData(indexName);
+                    
indexMetaData.getColumns().add(resultSet.getString("COLUMN_NAME"));
+                    
indexMetaData.setUnique(!resultSet.getBoolean("NON_UNIQUE"));
+                    result.put(indexName, indexMetaData);
+                } else {
+                    
result.get(indexName).getColumns().add(resultSet.getString("COLUMN_NAME"));
                 }
             }
         } catch (final SQLException ex) {
@@ -61,6 +70,6 @@ public final class IndexMetaDataLoader {
                 throw ex;
             }
         }
-        return result;
+        return result.values();
     }
 }
diff --git 
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/model/IndexMetaData.java
 
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/model/IndexMetaData.java
index d640fe26702..729f63aa6b3 100644
--- 
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/model/IndexMetaData.java
+++ 
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/data/model/IndexMetaData.java
@@ -20,8 +20,12 @@ package 
org.apache.shardingsphere.infra.database.core.metadata.data.model;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import lombok.ToString;
 
+import java.util.Collection;
+import java.util.LinkedList;
+
 /**
  * Index meta data.
  */
@@ -32,4 +36,9 @@ import lombok.ToString;
 public final class IndexMetaData {
     
     private final String name;
+    
+    private final Collection<String> columns = new LinkedList<>();
+    
+    @Setter
+    private boolean unique;
 }
diff --git 
a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java
 
b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java
index 1029aa8f58b..68689916eab 100644
--- 
a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java
+++ 
b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java
@@ -18,13 +18,13 @@
 package org.apache.shardingsphere.infra.database.mysql.metadata.data.loader;
 
 import org.apache.shardingsphere.infra.database.core.GlobalDataSourceRegistry;
-import 
org.apache.shardingsphere.infra.database.core.metadata.database.datatype.DataTypeLoader;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.loader.DialectMetaDataLoader;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.ColumnMetaData;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.ConstraintMetaData;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.IndexMetaData;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.SchemaMetaData;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.TableMetaData;
+import 
org.apache.shardingsphere.infra.database.core.metadata.database.datatype.DataTypeLoader;
 
 import javax.sql.DataSource;
 import java.sql.Connection;
@@ -55,7 +55,8 @@ public final class MySQLMetaDataLoader implements 
DialectMetaDataLoader {
     
     private static final String TABLE_META_DATA_SQL_IN_TABLES = 
TABLE_META_DATA_NO_ORDER + " AND TABLE_NAME IN (%s)" + 
ORDER_BY_ORDINAL_POSITION;
     
-    private static final String INDEX_META_DATA_SQL = "SELECT TABLE_NAME, 
INDEX_NAME FROM information_schema.statistics WHERE TABLE_SCHEMA=? and 
TABLE_NAME IN (%s)";
+    private static final String INDEX_META_DATA_SQL = "SELECT TABLE_NAME, 
INDEX_NAME, NON_UNIQUE, COLUMN_NAME FROM information_schema.statistics "
+            + "WHERE TABLE_SCHEMA=? and TABLE_NAME IN (%s) ORDER BY 
NON_UNIQUE, INDEX_NAME, SEQ_IN_INDEX";
     
     private static final String CONSTRAINT_META_DATA_SQL = "SELECT 
CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME FROM 
information_schema.KEY_COLUMN_USAGE "
             + "WHERE TABLE_NAME IN (%s) AND REFERENCED_TABLE_SCHEMA IS NOT 
NULL";
@@ -138,7 +139,7 @@ public final class MySQLMetaDataLoader implements 
DialectMetaDataLoader {
     }
     
     private Map<String, Collection<IndexMetaData>> loadIndexMetaData(final 
DataSource dataSource, final Collection<String> tableNames) throws SQLException 
{
-        Map<String, Collection<IndexMetaData>> result = new HashMap<>();
+        Map<String, Map<String, IndexMetaData>> tableToIndex = new HashMap<>();
         try (
                 Connection connection = dataSource.getConnection();
                 PreparedStatement preparedStatement = 
connection.prepareStatement(getIndexMetaDataSQL(tableNames))) {
@@ -148,13 +149,25 @@ public final class MySQLMetaDataLoader implements 
DialectMetaDataLoader {
                 while (resultSet.next()) {
                     String indexName = resultSet.getString("INDEX_NAME");
                     String tableName = resultSet.getString("TABLE_NAME");
-                    if (!result.containsKey(tableName)) {
-                        result.put(tableName, new LinkedList<>());
+                    if (!tableToIndex.containsKey(tableName)) {
+                        tableToIndex.put(tableName, new HashMap<>());
+                    }
+                    Map<String, IndexMetaData> indexMap = 
tableToIndex.get(tableName);
+                    if (!indexMap.containsKey(indexName)) {
+                        IndexMetaData indexMetaData = new 
IndexMetaData(indexName);
+                        
indexMetaData.getColumns().add(resultSet.getString("COLUMN_NAME"));
+                        
indexMetaData.setUnique("0".equals(resultSet.getString("NON_UNIQUE")));
+                        indexMap.put(indexName, indexMetaData);
+                    } else {
+                        
indexMap.get(indexName).getColumns().add(resultSet.getString("COLUMN_NAME"));
                     }
-                    result.get(tableName).add(new IndexMetaData(indexName));
                 }
             }
         }
+        Map<String, Collection<IndexMetaData>> result = new 
HashMap<>(tableToIndex.size(), 1);
+        for (Entry<String, Map<String, IndexMetaData>> entry : 
tableToIndex.entrySet()) {
+            result.put(entry.getKey(), entry.getValue().values());
+        }
         return result;
     }
     
diff --git 
a/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoaderTest.java
 
b/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoaderTest.java
index d7bc071aa4e..bfc0355c441 100644
--- 
a/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoaderTest.java
+++ 
b/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoaderTest.java
@@ -53,8 +53,8 @@ class MySQLMetaDataLoaderTest {
                 + "FROM information_schema.columns WHERE TABLE_SCHEMA=? ORDER 
BY ORDINAL_POSITION")
                 .executeQuery()).thenReturn(resultSet);
         ResultSet indexResultSet = mockIndexMetaDataResultSet();
-        when(dataSource.getConnection().prepareStatement("SELECT TABLE_NAME, 
INDEX_NAME "
-                + "FROM information_schema.statistics WHERE TABLE_SCHEMA=? and 
TABLE_NAME IN ('tbl')").executeQuery()).thenReturn(indexResultSet);
+        when(dataSource.getConnection().prepareStatement("SELECT TABLE_NAME, 
INDEX_NAME, NON_UNIQUE, COLUMN_NAME FROM information_schema.statistics "
+                + "WHERE TABLE_SCHEMA=? and TABLE_NAME IN ('tbl') ORDER BY 
NON_UNIQUE, INDEX_NAME, 
SEQ_IN_INDEX").executeQuery()).thenReturn(indexResultSet);
         assertTableMetaDataMap(dialectMetaDataLoader.load(dataSource, 
Collections.emptyList(), "sharding_db"));
     }
     
@@ -66,8 +66,8 @@ class MySQLMetaDataLoaderTest {
                 + "FROM information_schema.columns WHERE TABLE_SCHEMA=? AND 
TABLE_NAME IN ('tbl') ORDER BY ORDINAL_POSITION")
                 .executeQuery()).thenReturn(resultSet);
         ResultSet indexResultSet = mockIndexMetaDataResultSet();
-        when(dataSource.getConnection().prepareStatement(
-                "SELECT TABLE_NAME, INDEX_NAME FROM 
information_schema.statistics WHERE TABLE_SCHEMA=? and TABLE_NAME IN ('tbl')")
+        when(dataSource.getConnection().prepareStatement("SELECT TABLE_NAME, 
INDEX_NAME, NON_UNIQUE, COLUMN_NAME FROM information_schema.statistics WHERE 
TABLE_SCHEMA=? and TABLE_NAME IN ('tbl') "
+                + "ORDER BY NON_UNIQUE, INDEX_NAME, SEQ_IN_INDEX")
                 .executeQuery()).thenReturn(indexResultSet);
         assertTableMetaDataMap(dialectMetaDataLoader.load(dataSource, 
Collections.singletonList("tbl"), "sharding_db"));
     }
@@ -105,6 +105,8 @@ class MySQLMetaDataLoaderTest {
         when(result.next()).thenReturn(true, false);
         when(result.getString("INDEX_NAME")).thenReturn("id");
         when(result.getString("TABLE_NAME")).thenReturn("tbl");
+        when(result.getString("COLUMN_NAME")).thenReturn("id");
+        when(result.getString("NON_UNIQUE")).thenReturn("0");
         return result;
     }
     
@@ -124,6 +126,9 @@ class MySQLMetaDataLoaderTest {
         assertThat(columnsIterator.next(), is(new ColumnMetaData("mpt", 
Types.BINARY, false, false, false, true, false)));
         assertThat(actualTableMetaData.getIndexes().size(), is(1));
         Iterator<IndexMetaData> indexesIterator = 
actualTableMetaData.getIndexes().iterator();
-        assertThat(indexesIterator.next(), is(new IndexMetaData("id")));
+        IndexMetaData expected = new IndexMetaData("id");
+        expected.getColumns().add("id");
+        expected.setUnique(true);
+        assertThat(indexesIterator.next(), is(expected));
     }
 }
diff --git 
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/reviser/index/SingleIndexReviser.java
 
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/reviser/index/SingleIndexReviser.java
index 0cbb663808b..d7bce6da8d6 100644
--- 
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/reviser/index/SingleIndexReviser.java
+++ 
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/reviser/index/SingleIndexReviser.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.single.metadata.reviser.index;
 
-import 
org.apache.shardingsphere.infra.metadata.database.schema.reviser.index.IndexReviser;
 import 
org.apache.shardingsphere.infra.database.core.metadata.data.model.IndexMetaData;
+import 
org.apache.shardingsphere.infra.metadata.database.schema.reviser.index.IndexReviser;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.util.IndexMetaDataUtils;
 import org.apache.shardingsphere.single.rule.SingleRule;
 
@@ -31,6 +31,9 @@ public final class SingleIndexReviser implements 
IndexReviser<SingleRule> {
     
     @Override
     public Optional<IndexMetaData> revise(final String tableName, final 
IndexMetaData originalMetaData, final SingleRule singleRule) {
-        return Optional.of(new 
IndexMetaData(IndexMetaDataUtils.getLogicIndexName(originalMetaData.getName(), 
tableName)));
+        IndexMetaData result = new 
IndexMetaData(IndexMetaDataUtils.getLogicIndexName(originalMetaData.getName(), 
tableName));
+        result.getColumns().addAll(originalMetaData.getColumns());
+        result.setUnique(originalMetaData.isUnique());
+        return Optional.of(result);
     }
 }
diff --git 
a/test/e2e/sql/src/test/resources/env/scenario/db/data/actual/init-sql/mysql/01-actual-init.sql
 
b/test/e2e/sql/src/test/resources/env/scenario/db/data/actual/init-sql/mysql/01-actual-init.sql
index 1bca1e989ce..ba743d2f80d 100644
--- 
a/test/e2e/sql/src/test/resources/env/scenario/db/data/actual/init-sql/mysql/01-actual-init.sql
+++ 
b/test/e2e/sql/src/test/resources/env/scenario/db/data/actual/init-sql/mysql/01-actual-init.sql
@@ -46,7 +46,7 @@ CREATE TABLE db_0.t_user (user_id INT PRIMARY KEY, user_name 
VARCHAR(50) NOT NUL
 CREATE TABLE db_0.t_product (product_id INT PRIMARY KEY, product_name 
VARCHAR(50) NOT NULL, category_id INT NOT NULL, price DECIMAL NOT NULL, status 
VARCHAR(50) NOT NULL, creation_date DATE NOT NULL);
 CREATE TABLE db_0.t_product_category (category_id INT PRIMARY KEY, 
category_name VARCHAR(50) NOT NULL, parent_id INT NOT NULL, level TINYINT NOT 
NULL, creation_date DATE NOT NULL);
 CREATE TABLE db_0.t_country (country_id SMALLINT PRIMARY KEY, country_name 
VARCHAR(50), continent_name VARCHAR(50), creation_date DATE NOT NULL);
-CREATE TABLE db_0.t_single_table (single_id INT NOT NULL, id INT NOT NULL, 
status VARCHAR(45) NULL, PRIMARY KEY (single_id));
+CREATE TABLE db_0.t_single_table (single_id INT NOT NULL, id INT NOT NULL, 
status VARCHAR(45) NULL, PRIMARY KEY (single_id), UNIQUE KEY (id, status));
 CREATE TABLE db_0.t_broadcast_table (id INT NOT NULL, status VARCHAR(45) NULL, 
PRIMARY KEY (id));
 CREATE INDEX order_index_t_order ON db_0.t_order (order_id);
 
diff --git 
a/test/e2e/sql/src/test/resources/env/scenario/db/data/expected/init-sql/mysql/01-expected-init.sql
 
b/test/e2e/sql/src/test/resources/env/scenario/db/data/expected/init-sql/mysql/01-expected-init.sql
index 1327477588c..f0b1435515d 100644
--- 
a/test/e2e/sql/src/test/resources/env/scenario/db/data/expected/init-sql/mysql/01-expected-init.sql
+++ 
b/test/e2e/sql/src/test/resources/env/scenario/db/data/expected/init-sql/mysql/01-expected-init.sql
@@ -34,7 +34,7 @@ CREATE VIEW expected_dataset.t_order_subquery_view AS SELECT 
* FROM expected_dat
 CREATE VIEW expected_dataset.t_order_aggregation_view AS SELECT MAX(p.price) 
AS max_price, MIN(p.price) AS min_price, SUM(p.price) AS sum_price, 
AVG(p.price) AS avg_price, COUNT(1) AS count FROM expected_dataset.t_order o 
INNER JOIN expected_dataset.t_order_item i ON o.order_id = i.order_id INNER 
JOIN expected_dataset.t_product p ON i.product_id = p.product_id GROUP BY 
o.order_id HAVING SUM(p.price) > 10000 ORDER BY max_price;
 CREATE VIEW expected_dataset.t_order_union_view AS SELECT * FROM 
expected_dataset.t_order WHERE order_id > 2000 UNION SELECT * FROM 
expected_dataset.t_order WHERE order_id > 1500;
 -- TODO replace these tables with standard tables
-CREATE TABLE expected_dataset.t_single_table (single_id INT NOT NULL, id INT 
NOT NULL, status VARCHAR(45) NULL, PRIMARY KEY (single_id));
+CREATE TABLE expected_dataset.t_single_table (single_id INT NOT NULL, id INT 
NOT NULL, status VARCHAR(45) NULL, PRIMARY KEY (single_id), UNIQUE KEY (id, 
status));
 CREATE TABLE expected_dataset.t_broadcast_table (id INT NOT NULL, status 
VARCHAR(45) NULL, PRIMARY KEY (id));
 
 CREATE INDEX order_index_t_order ON expected_dataset.t_order (order_id);

Reply via email to