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

menghaoran 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 484332cfa1d Fix the generated key column name case insensitivity 
error(#32756) (#32763)
484332cfa1d is described below

commit 484332cfa1db442de6ace8956f1d49051047ef4a
Author: ZhangCheng <[email protected]>
AuthorDate: Mon Sep 2 14:52:21 2024 +0800

    Fix the generated key column name case insensitivity error(#32756) (#32763)
    
    * Fix the generated key column name case insensitivity error
    
    * Fix the generated key column name case insensitivity error
    
    * Fix the generated key column name case insensitivity error
    
    * Fix the generated key column name case insensitivity error
    
    * Fix the generated key column name case insensitivity error
    
    * Fix the generated key column name case insensitivity error
    
    * Fix the generated key column name case insensitivity error
---
 .../keygen/engine/GeneratedKeyContextEngine.java   | 27 +++++++++++-----------
 .../statement/dml/InsertStatementContext.java      | 21 +++++++++++++++--
 .../engine/GeneratedKeyContextEngineTest.java      |  9 ++++----
 .../schema/model/ShardingSphereSchema.java         | 10 ++++++++
 .../database/schema/model/ShardingSphereTable.java |  4 ++++
 .../db/insert_single_with_generate_key_column.xml  | 24 +++++++++++++++++++
 .../test/resources/cases/dml/e2e-dml-insert.xml    | 24 +++++++++++++++++++
 .../data/actual/init-sql/mysql/01-actual-init.sql  |  1 +
 8 files changed, 101 insertions(+), 19 deletions(-)

diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngine.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngine.java
index 1814c368352..83aa7d0c89b 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngine.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngine.java
@@ -17,7 +17,6 @@
 
 package 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.engine;
 
-import com.cedarsoftware.util.CaseInsensitiveSet;
 import lombok.RequiredArgsConstructor;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.GeneratedKeyContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertValueContext;
@@ -30,6 +29,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simp
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.InsertStatement;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -45,15 +45,16 @@ public final class GeneratedKeyContextEngine {
     /**
      * Create generate key context.
      *
-     * @param insertColumnNames insert column names
+     * @param insertColumnNamesAndIndexes insert column names and indexes
      * @param insertValueContexts insert value contexts
      * @param params SQL parameters
      * @return generate key context
      */
-    public Optional<GeneratedKeyContext> createGenerateKeyContext(final 
List<String> insertColumnNames, final List<InsertValueContext> 
insertValueContexts, final List<Object> params) {
+    public Optional<GeneratedKeyContext> createGenerateKeyContext(final 
Map<String, Integer> insertColumnNamesAndIndexes, final 
List<InsertValueContext> insertValueContexts,
+                                                                  final 
List<Object> params) {
         String tableName = 
Optional.ofNullable(insertStatement.getTable()).map(optional -> 
optional.getTableName().getIdentifier().getValue()).orElse("");
-        return findGenerateKeyColumn(tableName).map(optional -> 
containsGenerateKey(insertColumnNames, optional)
-                ? findGeneratedKey(insertColumnNames, insertValueContexts, 
params, optional)
+        return findGenerateKeyColumn(tableName).map(optional -> 
containsGenerateKey(insertColumnNamesAndIndexes, optional)
+                ? findGeneratedKey(insertColumnNamesAndIndexes, 
insertValueContexts, params, optional)
                 : new GeneratedKeyContext(optional, true));
     }
     
@@ -69,9 +70,9 @@ public final class GeneratedKeyContextEngine {
         return Optional.empty();
     }
     
-    private boolean containsGenerateKey(final List<String> insertColumnNames, 
final String generateKeyColumnName) {
-        return insertColumnNames.isEmpty() ? 
schema.getVisibleColumnNames(insertStatement.getTable().getTableName().getIdentifier().getValue()).size()
 == getValueCountForPerGroup()
-                : new 
CaseInsensitiveSet<>(insertColumnNames).contains(generateKeyColumnName);
+    private boolean containsGenerateKey(final Map<String, Integer> 
insertColumnNamesAndIndexes, final String generateKeyColumnName) {
+        return insertColumnNamesAndIndexes.isEmpty() ? 
schema.getVisibleColumnNames(insertStatement.getTable().getTableName().getIdentifier().getValue()).size()
 == getValueCountForPerGroup()
+                : 
insertColumnNamesAndIndexes.containsKey(generateKeyColumnName);
     }
     
     private int getValueCountForPerGroup() {
@@ -88,11 +89,11 @@ public final class GeneratedKeyContextEngine {
         return 0;
     }
     
-    private GeneratedKeyContext findGeneratedKey(final List<String> 
insertColumnNames, final List<InsertValueContext> insertValueContexts,
+    private GeneratedKeyContext findGeneratedKey(final Map<String, Integer> 
insertColumnNamesAndIndexes, final List<InsertValueContext> insertValueContexts,
                                                  final List<Object> params, 
final String generateKeyColumnName) {
         GeneratedKeyContext result = new 
GeneratedKeyContext(generateKeyColumnName, false);
         for (InsertValueContext each : insertValueContexts) {
-            ExpressionSegment expression = 
each.getValueExpressions().get(findGenerateKeyIndex(insertColumnNames, 
generateKeyColumnName.toLowerCase()));
+            ExpressionSegment expression = 
each.getValueExpressions().get(findGenerateKeyIndex(insertColumnNamesAndIndexes,
 generateKeyColumnName));
             if (expression instanceof ParameterMarkerExpressionSegment) {
                 if (params.isEmpty()) {
                     continue;
@@ -107,8 +108,8 @@ public final class GeneratedKeyContextEngine {
         return result;
     }
     
-    private int findGenerateKeyIndex(final List<String> insertColumnNames, 
final String generateKeyColumnName) {
-        return insertColumnNames.isEmpty() ? 
schema.getVisibleColumnNames(insertStatement.getTable().getTableName().getIdentifier().getValue()).indexOf(generateKeyColumnName)
-                : insertColumnNames.indexOf(generateKeyColumnName);
+    private int findGenerateKeyIndex(final Map<String, Integer> 
insertColumnNamesAndIndexes, final String generateKeyColumnName) {
+        return insertColumnNamesAndIndexes.isEmpty() ? 
schema.getVisibleColumnNamesAndIndexes(insertStatement.getTable().getTableName().getIdentifier().getValue()).get(generateKeyColumnName)
+                : insertColumnNamesAndIndexes.get(generateKeyColumnName);
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/InsertStatementContext.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/InsertStatementContext.java
index 1c286242341..f86867aa3d7 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/InsertStatementContext.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/InsertStatementContext.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.infra.binder.context.statement.dml;
 
+import com.cedarsoftware.util.CaseInsensitiveMap;
 import lombok.Getter;
 import org.apache.shardingsphere.infra.binder.context.aware.ParameterAware;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.GeneratedKeyContext;
@@ -52,6 +53,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -66,6 +68,8 @@ public final class InsertStatementContext extends 
CommonSQLStatementContext impl
     
     private final List<String> insertColumnNames;
     
+    private final Map<String, Integer> insertColumnNamesAndIndexes;
+    
     private final List<List<ExpressionSegment>> valueExpressions;
     
     @Getter
@@ -99,7 +103,20 @@ public final class InsertStatementContext extends 
CommonSQLStatementContext impl
         ShardingSphereSchema schema = getSchema(metaData, currentDatabaseName);
         columnNames = containsInsertColumns() ? insertColumnNames
                 : Optional.ofNullable(sqlStatement.getTable()).map(optional -> 
schema.getVisibleColumnNames(optional.getTableName().getIdentifier().getValue())).orElseGet(Collections::emptyList);
-        generatedKeyContext = new GeneratedKeyContextEngine(sqlStatement, 
schema).createGenerateKeyContext(insertColumnNames, insertValueContexts, 
params).orElse(null);
+        insertColumnNamesAndIndexes = 
createInsertColumnNamesAndIndexes(sqlStatement, schema, insertColumnNames);
+        generatedKeyContext = new GeneratedKeyContextEngine(sqlStatement, 
schema).createGenerateKeyContext(insertColumnNamesAndIndexes, 
insertValueContexts, params).orElse(null);
+    }
+    
+    private Map<String, Integer> createInsertColumnNamesAndIndexes(final 
InsertStatement sqlStatement, final ShardingSphereSchema schema, final 
List<String> insertColumnNames) {
+        if (containsInsertColumns()) {
+            Map<String, Integer> result = new 
CaseInsensitiveMap<>(insertColumnNames.size(), 1F);
+            int index = 0;
+            for (String each : insertColumnNames) {
+                result.put(each, index++);
+            }
+            return result;
+        }
+        return Collections.emptyMap();
     }
     
     private List<InsertValueContext> getInsertValueContexts(final List<Object> 
params, final AtomicInteger paramsOffset, final List<List<ExpressionSegment>> 
valueExpressions) {
@@ -273,6 +290,6 @@ public final class InsertStatementContext extends 
CommonSQLStatementContext impl
         insertSelectContext = getInsertSelectContext(metaData, params, 
parametersOffset, currentDatabaseName).orElse(null);
         onDuplicateKeyUpdateValueContext = 
getOnDuplicateKeyUpdateValueContext(params, parametersOffset).orElse(null);
         ShardingSphereSchema schema = getSchema(metaData, currentDatabaseName);
-        generatedKeyContext = new GeneratedKeyContextEngine(getSqlStatement(), 
schema).createGenerateKeyContext(insertColumnNames, insertValueContexts, 
params).orElse(null);
+        generatedKeyContext = new GeneratedKeyContextEngine(getSqlStatement(), 
schema).createGenerateKeyContext(insertColumnNamesAndIndexes, 
insertValueContexts, params).orElse(null);
     }
 }
diff --git 
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngineTest.java
 
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngineTest.java
index 659070cb4b0..ede9e8f3e9d 100644
--- 
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngineTest.java
+++ 
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/insert/keygen/engine/GeneratedKeyContextEngineTest.java
@@ -17,6 +17,7 @@
 
 package 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.engine;
 
+import com.cedarsoftware.util.CaseInsensitiveMap;
 import com.google.common.collect.ImmutableMap;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.GeneratedKeyContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertValueContext;
@@ -96,7 +97,7 @@ class GeneratedKeyContextEngineTest {
     private void 
assertCreateGenerateKeyContextWithoutGenerateKeyColumnConfiguration(final 
InsertStatement insertStatement) {
         insertStatement.setTable(new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue("tbl1"))));
         insertStatement.setInsertColumns(new InsertColumnsSegment(0, 0, 
Collections.singletonList(new ColumnSegment(0, 0, new IdentifierValue("id")))));
-        assertFalse(new GeneratedKeyContextEngine(insertStatement, 
schema).createGenerateKeyContext(Collections.emptyList(),
+        assertFalse(new GeneratedKeyContextEngine(insertStatement, 
schema).createGenerateKeyContext(Collections.emptyMap(),
                 Collections.emptyList(), 
Collections.singletonList(1)).isPresent());
     }
     
@@ -141,7 +142,7 @@ class GeneratedKeyContextEngineTest {
         InsertValueContext insertValueContext = new 
InsertValueContext(expressionSegments, Collections.emptyList(), 0);
         insertStatement.getValues().add(new InsertValuesSegment(0, 0, 
expressionSegments));
         Optional<GeneratedKeyContext> actual = new 
GeneratedKeyContextEngine(insertStatement, schema)
-                .createGenerateKeyContext(Collections.singletonList("id"), 
Collections.singletonList(insertValueContext), Collections.singletonList(1));
+                .createGenerateKeyContext(new 
CaseInsensitiveMap<>(Collections.singletonMap("id", 0)), 
Collections.singletonList(insertValueContext), Collections.singletonList(1));
         assertTrue(actual.isPresent());
         assertThat(actual.get().getGeneratedValues().size(), is(1));
     }
@@ -181,13 +182,13 @@ class GeneratedKeyContextEngineTest {
         List<InsertValueContext> insertValueContexts = 
insertStatement.getValues().stream()
                 .map(each -> new InsertValueContext(each.getValues(), 
Collections.emptyList(), 0)).collect(Collectors.toList());
         Optional<GeneratedKeyContext> actual = new 
GeneratedKeyContextEngine(insertStatement, schema)
-                .createGenerateKeyContext(Collections.singletonList("id"), 
insertValueContexts, Collections.singletonList(1));
+                .createGenerateKeyContext(Collections.singletonMap("id", 0), 
insertValueContexts, Collections.singletonList(1));
         assertTrue(actual.isPresent());
         assertThat(actual.get().getGeneratedValues().size(), is(3));
         Iterator<Comparable<?>> generatedValuesIterator = 
actual.get().getGeneratedValues().iterator();
         assertThat(generatedValuesIterator.next(), is(1));
         assertThat(generatedValuesIterator.next(), is(100));
         assertThat(generatedValuesIterator.next(), is("value"));
-        assertTrue(new GeneratedKeyContextEngine(insertStatement, 
schema).createGenerateKeyContext(Collections.emptyList(), 
Collections.emptyList(), Collections.singletonList(1)).isPresent());
+        assertTrue(new GeneratedKeyContextEngine(insertStatement, 
schema).createGenerateKeyContext(Collections.emptyMap(), 
Collections.emptyList(), Collections.singletonList(1)).isPresent());
     }
 }
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereSchema.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereSchema.java
index d19254dee17..3d748287706 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereSchema.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereSchema.java
@@ -202,6 +202,16 @@ public final class ShardingSphereSchema {
         return containsTable(tableName) ? 
getTable(tableName).getVisibleColumns() : Collections.emptyList();
     }
     
+    /**
+     * Get visible column names and indexes via table.
+     *
+     * @param tableName table name
+     * @return visible column names and indexes
+     */
+    public Map<String, Integer> getVisibleColumnNamesAndIndexes(final String 
tableName) {
+        return containsTable(tableName) ? 
getTable(tableName).getVisibleColumnsAndIndexes() : Collections.emptyMap();
+    }
+    
     /**
      *  Schema is empty or not.
      * @return true if tables and views are all empty, else false
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereTable.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereTable.java
index bd5eb1db5a5..b87cf50b9c6 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereTable.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/model/ShardingSphereTable.java
@@ -49,6 +49,8 @@ public final class ShardingSphereTable {
     
     private final List<String> visibleColumns = new ArrayList<>();
     
+    private final Map<String, Integer> visibleColumnsAndIndexes = new 
CaseInsensitiveMap<>();
+    
     private final List<String> primaryKeyColumns = new ArrayList<>();
     
     private final TableType type;
@@ -77,6 +79,7 @@ public final class ShardingSphereTable {
     
     private Map<String, ShardingSphereColumn> createColumns(final 
Collection<ShardingSphereColumn> columns) {
         Map<String, ShardingSphereColumn> result = new 
CaseInsensitiveMap<>(columns.size(), 1F);
+        int index = 0;
         for (ShardingSphereColumn each : columns) {
             result.put(each.getName(), each);
             columnNames.add(each.getName());
@@ -85,6 +88,7 @@ public final class ShardingSphereTable {
             }
             if (each.isVisible()) {
                 visibleColumns.add(each.getName());
+                visibleColumnsAndIndexes.put(each.getName(), index++);
             }
         }
         return result;
diff --git 
a/test/e2e/sql/src/test/resources/cases/dml/dataset/db/insert_single_with_generate_key_column.xml
 
b/test/e2e/sql/src/test/resources/cases/dml/dataset/db/insert_single_with_generate_key_column.xml
new file mode 100644
index 00000000000..4c811b81cd2
--- /dev/null
+++ 
b/test/e2e/sql/src/test/resources/cases/dml/dataset/db/insert_single_with_generate_key_column.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ 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.
+  -->
+
+<dataset update-count="1">
+    <metadata data-nodes="db_0.t_single">
+        <column name="id" type="numeric" />
+        <column name="name" type="varchar" />
+    </metadata>
+    <row data-node="db_0.t_single" values="1, 1" />
+</dataset>
diff --git a/test/e2e/sql/src/test/resources/cases/dml/e2e-dml-insert.xml 
b/test/e2e/sql/src/test/resources/cases/dml/e2e-dml-insert.xml
index a582af0ec59..eff31f59f11 100644
--- a/test/e2e/sql/src/test/resources/cases/dml/e2e-dml-insert.xml
+++ b/test/e2e/sql/src/test/resources/cases/dml/e2e-dml-insert.xml
@@ -233,4 +233,28 @@
     <test-case sql="/* SHARDINGSPHERE_HINT: DATA_SOURCE_NAME=encrypt_ds_0 
*/INSERT INTO t_order_0 values (1, 1, 'ok', 1, 'mark', '2021-01-01')" 
db-types="MySQL,PostgreSQL" scenario-types="sharding_and_encrypt">
         <assertion expected-data-file="insert_into_t_order_0.xml" />
     </test-case>
+    
+    <test-case sql="INSERT INTO t_single values (?, ?)" db-types="MySQL" 
scenario-types="db">
+        <assertion parameters="1:int, 1:int" 
expected-data-file="insert_single_with_generate_key_column.xml" >
+            <destroy-sql sql="DELETE FROM t_single WHERE id = 1" />
+        </assertion>
+    </test-case>
+    
+    <test-case sql="INSERT INTO t_single(Id, Name) values (?, ?)" 
db-types="MySQL" scenario-types="db">
+        <assertion parameters="1:int, 1:int" 
expected-data-file="insert_single_with_generate_key_column.xml" >
+            <destroy-sql sql="DELETE FROM t_single WHERE id = 1" />
+        </assertion>
+    </test-case>
+    
+    <test-case sql="INSERT INTO t_single(id, name) values (?, ?)" 
db-types="MySQL" scenario-types="db">
+        <assertion parameters="1:int, 1:int" 
expected-data-file="insert_single_with_generate_key_column.xml" >
+            <destroy-sql sql="DELETE FROM t_single WHERE id = 1" />
+        </assertion>
+    </test-case>
+    
+    <test-case sql="INSERT INTO t_single(ID, NAME) values (?, ?)" 
db-types="MySQL" scenario-types="db">
+        <assertion parameters="1:int, 1:int" 
expected-data-file="insert_single_with_generate_key_column.xml" >
+            <destroy-sql sql="DELETE FROM t_single WHERE id = 1" />
+        </assertion>
+    </test-case>
 </e2e-test-cases>
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 ae1f7965b83..0c853234d86 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,6 +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 (ID BIGINT PRIMARY KEY, NAME VARCHAR(50));
 CREATE INDEX order_index ON db_0.t_order (order_id);
 
 CREATE TABLE db_1.t_order (order_id BIGINT PRIMARY KEY, user_id INT NOT NULL, 
status VARCHAR(50) NOT NULL, merchant_id INT, remark VARCHAR(50) NOT NULL, 
creation_date DATE NOT NULL);

Reply via email to