Copilot commented on code in PR #37778:
URL: https://github.com/apache/shardingsphere/pull/37778#discussion_r2706794987


##########
docs/document/content/user-manual/shardingsphere-jdbc/distsql/_index.en.md:
##########
@@ -0,0 +1,121 @@
++++
+title = "DistSQL"
+weight = 6
+chapter = true
++++
+
+# Background Information
+
+Currently, DistSQL can be executed via ShardingSphere JDBC DataSource to 
dynamically modify ShardingSphere configuration.
+
+# Configuration Example
+
+## Prerequisites
+
+Include the following dependencies in your business project:
+
+```xml
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc-dialect-mysql</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-data-source-pool-hikari</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-url-classpath</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-standalone-mode-repository-memory</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-sharding-core</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-authority-simple</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>com.h2database</groupId>
+    <artifactId>h2</artifactId>
+    <version>2.2.224</version>
+</dependency>
+```
+
+Write the ShardingSphere data source configuration file `demo.yaml` on the 
classpath of your business project.
+
+```yaml
+props:
+  sql-show: false
+```
+
+## Enjoy the Integration
+
+Create a ShardingSphere data source to enjoy integration.
+
+```java
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+public class ExampleUtils {
+    void test() throws SQLException {

Review Comment:
   The class name ExampleUtils with a test() method is not a conventional 
naming pattern for example code. The method should typically be named main() or 
have a more descriptive name that indicates what it demonstrates. Consider 
renaming the class to something like DistSQLExample and the method to 
demonstrateDistSQLUsage() or similar.
   ```suggestion
   public class DistSQLExample {
       void demonstrateDistSQLUsage() throws SQLException {
   ```



##########
jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/DistSQLStatementContext.java:
##########
@@ -0,0 +1,41 @@
+/*
+ * 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.driver.jdbc.core.statement;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.distsql.statement.DistSQLStatement;
+import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+
+import java.util.Collections;
+
+/**
+ * SQL statement context for DistSQL.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class DistSQLStatementContext implements SQLStatementContext {
+    
+    private final DistSQLStatement sqlStatement;

Review Comment:
   This method overrides [SQLStatementContext.getSqlStatement](1); it is 
advisable to add an Override annotation.



##########
docs/document/content/user-manual/shardingsphere-jdbc/distsql/_index.cn.md:
##########
@@ -0,0 +1,120 @@
++++
+title = "DistSQL"
+weight = 6
+chapter = true
++++
+
+# 背景信息
+
+当前可以通过 ShardingSphere JDBC DataSource 执行 DistSQL,以动态修改 ShardingSphere 配置。
+
+# 配置示例
+
+## 前提条件
+
+在业务项目引入如下依赖,
+
+```xml
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc-dialect-mysql</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-data-source-pool-hikari</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-url-classpath</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-standalone-mode-repository-memory</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-sharding-core</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-authority-simple</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>com.h2database</groupId>
+    <artifactId>h2</artifactId>
+    <version>2.2.224</version>
+</dependency>
+```
+
+在业务项目的 classpath 上编写 ShardingSphere 数据源的配置文件 `demo.yaml`,
+
+```yaml
+props:
+  sql-show: false
+```
+
+## 享受集成
+
+创建 ShardingSphere 的数据源以享受集成,
+
+```java
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+public class ExampleUtils {
+    void test() throws SQLException {
+        HikariConfig config = new HikariConfig();
+        config.setJdbcUrl("jdbc:shardingsphere:classpath:demo.yaml");
+        
config.setDriverClassName("org.apache.shardingsphere.driver.ShardingSphereDriver");
+        try (HikariDataSource dataSource = new HikariDataSource(config);
+             Connection connection = dataSource.getConnection();
+             Statement statement = connection.createStatement()) {
+            statement.execute("register storage unit ds_0 
(url='jdbc:h2:mem:local_sharding_ds_0;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE',user='sa',password=''),
 ds_1 
(url='jdbc:h2:mem:local_sharding_ds_1;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE',user='sa',password=''),
 ds_2 
(url='jdbc:h2:mem:local_sharding_ds_2;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE',user='sa',password='')");
+            statement.execute("create default sharding database strategy 
(type='standard', 
sharding_column=user_id,sharding_algorithm(type(name=class_based, 
properties('strategy'='STANDARD', 
'algorithmClassName'='org.apache.shardingsphere.test.natived.commons.algorithm.ClassBasedInlineShardingAlgorithmFixture'))))");
+            statement.execute("create sharding table rule t_order 
(datanodes('<LITERAL>ds_0.t_order, ds_1.t_order, ds_2.t_order'), 
key_generate_strategy(column=order_id,type(name='SNOWFLAKE'))), t_order_item 
(datanodes('<LITERAL>ds_0.t_order_item, ds_1.t_order_item, ds_2.t_order_item'), 
key_generate_strategy(column=order_item_id,type(name='SNOWFLAKE')))");
+            statement.execute("create broadcast table rule t_address");
+            statement.execute("CREATE TABLE IF NOT EXISTS t_order (order_id 
BIGINT NOT NULL AUTO_INCREMENT,order_type INT(11),user_id INT NOT 
NULL,address_id BIGINT NOT NULL,status VARCHAR(50),PRIMARY KEY (order_id))");
+            statement.execute("TRUNCATE TABLE t_order");
+            statement.execute("INSERT INTO t_order (user_id, order_type, 
address_id, status) VALUES (1, 1, 1, 'INSERT_TEST')");
+            statement.executeQuery("SELECT * FROM t_order");

Review Comment:
   The ResultSet returned by statement.executeQuery on line 92 is not closed, 
which could lead to a resource leak. The ResultSet should be wrapped in a 
try-with-resources block or explicitly closed after use.
   ```suggestion
               try (java.sql.ResultSet resultSet = 
statement.executeQuery("SELECT * FROM t_order")) {
                   // process resultSet if needed
               }
   ```



##########
jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java:
##########
@@ -242,25 +301,36 @@ public boolean execute(final String sql, final String[] 
columnNames) throws SQLE
         }
     }
     
-    private boolean execute(final String sql, final StatementExecuteCallback 
statementExecuteCallback) throws SQLException {
+    private boolean execute(final SQLStatement sqlStatement, final String sql, 
final StatementExecuteCallback statementExecuteCallback) throws SQLException {
         currentResultSet = null;
-        QueryContext queryContext = createQueryContext(sql);
+        QueryContext queryContext = createQueryContext(sqlStatement, sql);
         prepareExecute(queryContext);
         ShardingSphereDatabase usedDatabase = 
metaData.getDatabase(usedDatabaseName);
         return driverExecutorFacade.execute(usedDatabase, metaData, 
queryContext, statementExecuteCallback,
                 (StatementAddCallback<Statement>) (statements, parameterSets) 
-> this.statements.addAll(statements), this::replay);
     }
     
-    private QueryContext createQueryContext(final String originSQL) throws 
SQLException {
+    private SQLStatement parseSql(final String originSQL) throws SQLException {
         ShardingSpherePreconditions.checkNotEmpty(originSQL, () -> new 
EmptySQLException().toSQLException());
-        HintValueContext hintValueContext = 
SQLHintUtils.extractHint(originSQL);
         String sql = SQLHintUtils.removeHint(originSQL);
         DatabaseType databaseType = 
metaData.getDatabase(usedDatabaseName).getProtocolType();
-        SQLStatement sqlStatement = 
metaData.getGlobalRuleMetaData().getSingleRule(SQLParserRule.class).getSQLParserEngine(databaseType).parse(sql,
 false);
+        return 
metaData.getGlobalRuleMetaData().getSingleRule(SQLParserRule.class).getSQLParserEngine(databaseType).parse(sql,
 false);
+    }
+    
+    private QueryContext createQueryContext(final SQLStatement sqlStatement, 
final String originSQL) throws SQLException {
+        HintValueContext hintValueContext = 
SQLHintUtils.extractHint(originSQL);
+        String sql = SQLHintUtils.removeHint(originSQL);
         SQLStatementContext sqlStatementContext = new SQLBindEngine(metaData, 
connection.getCurrentDatabaseName(), hintValueContext).bind(sqlStatement);
         return new QueryContext(sqlStatementContext, sql, 
Collections.emptyList(), hintValueContext, 
connection.getDatabaseConnectionManager().getConnectionContext(), metaData);
     }
     
+    private QueryContext createDistSQLQueryContext(final DistSQLStatement 
sqlStatement, final String originSQL) throws SQLException {
+        HintValueContext hintValueContext = 
SQLHintUtils.extractHint(originSQL);
+        String sql = SQLHintUtils.removeHint(originSQL);
+        SQLStatementContext sqlStatementContext = new 
DistSQLStatementContext(sqlStatement);
+        return new QueryContext(sqlStatementContext, sql, 
Collections.emptyList(), hintValueContext, 
connection.getDatabaseConnectionManager().getConnectionContext(), metaData);
+    }

Review Comment:
   The hint removal operation SQLHintUtils.removeHint is performed twice: once 
in parseSql and again in createQueryContext/createDistSQLQueryContext. Since 
parseSql already removes hints before parsing, the createQueryContext and 
createDistSQLQueryContext methods should receive the already processed SQL 
string instead of re-processing the original SQL. This redundant processing 
affects performance.



##########
docs/document/content/user-manual/shardingsphere-jdbc/distsql/_index.en.md:
##########
@@ -0,0 +1,121 @@
++++
+title = "DistSQL"
+weight = 6
+chapter = true
++++
+
+# Background Information
+
+Currently, DistSQL can be executed via ShardingSphere JDBC DataSource to 
dynamically modify ShardingSphere configuration.
+
+# Configuration Example
+
+## Prerequisites
+
+Include the following dependencies in your business project:
+
+```xml
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc-dialect-mysql</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-data-source-pool-hikari</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-url-classpath</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-standalone-mode-repository-memory</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-sharding-core</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-authority-simple</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>com.h2database</groupId>
+    <artifactId>h2</artifactId>
+    <version>2.2.224</version>
+</dependency>
+```
+
+Write the ShardingSphere data source configuration file `demo.yaml` on the 
classpath of your business project.
+
+```yaml
+props:
+  sql-show: false
+```
+
+## Enjoy the Integration
+
+Create a ShardingSphere data source to enjoy integration.
+
+```java
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+public class ExampleUtils {
+    void test() throws SQLException {
+        HikariConfig config = new HikariConfig();
+        config.setJdbcUrl("jdbc:shardingsphere:classpath:demo.yaml");
+        
config.setDriverClassName("org.apache.shardingsphere.driver.ShardingSphereDriver");
+        try (HikariDataSource dataSource = new HikariDataSource(config);
+             Connection connection = dataSource.getConnection();
+             Statement statement = connection.createStatement()) {
+            statement.execute("register storage unit ds_0 
(url='jdbc:h2:mem:local_sharding_ds_0;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE',user='sa',password=''),
 ds_1 
(url='jdbc:h2:mem:local_sharding_ds_1;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE',user='sa',password=''),
 ds_2 
(url='jdbc:h2:mem:local_sharding_ds_2;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE',user='sa',password='')");
+            statement.execute("create default sharding database strategy 
(type='standard', 
sharding_column=user_id,sharding_algorithm(type(name=class_based, 
properties('strategy'='STANDARD', 
'algorithmClassName'='org.apache.shardingsphere.test.natived.commons.algorithm.ClassBasedInlineShardingAlgorithmFixture'))))");
+            statement.execute("create sharding table rule t_order 
(datanodes('<LITERAL>ds_0.t_order, ds_1.t_order, ds_2.t_order'), 
key_generate_strategy(column=order_id,type(name='SNOWFLAKE'))), t_order_item 
(datanodes('<LITERAL>ds_0.t_order_item, ds_1.t_order_item, ds_2.t_order_item'), 
key_generate_strategy(column=order_item_id,type(name='SNOWFLAKE')))");
+            statement.execute("create broadcast table rule t_address");
+            statement.execute("CREATE TABLE IF NOT EXISTS t_order (order_id 
BIGINT NOT NULL AUTO_INCREMENT,order_type INT(11),user_id INT NOT 
NULL,address_id BIGINT NOT NULL,status VARCHAR(50),PRIMARY KEY (order_id))");
+            statement.execute("TRUNCATE TABLE t_order");
+            statement.execute("INSERT INTO t_order (user_id, order_type, 
address_id, status) VALUES (1, 1, 1, 'INSERT_TEST')");
+            statement.executeQuery("SELECT * FROM t_order");

Review Comment:
   The ResultSet returned by statement.executeQuery on line 92 is not closed, 
which could lead to a resource leak. The ResultSet should be wrapped in a 
try-with-resources block or explicitly closed after use.
   ```suggestion
               try (java.sql.ResultSet resultSet = 
statement.executeQuery("SELECT * FROM t_order")) {
                   // Process the result set if needed.
               }
   ```



##########
jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/distsql/DistSQLResultSet.java:
##########
@@ -0,0 +1,270 @@
+/*
+ * 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.driver.executor.engine.distsql;
+
+import com.google.common.base.Preconditions;
+import 
org.apache.shardingsphere.driver.jdbc.unsupported.AbstractUnsupportedGeneratedKeysResultSet;
+import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.nio.charset.StandardCharsets;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * DistSQL result set.
+ */
+public final class DistSQLResultSet extends 
AbstractUnsupportedGeneratedKeysResultSet {
+    
+    private final List<String> columnNames;
+    
+    private final Iterator<LocalDataQueryResultRow> rows;
+    
+    private final Statement statement;
+    
+    private LocalDataQueryResultRow currentRow;
+    
+    private boolean closed;
+    
+    private boolean lastReadWasNull;
+    
+    public DistSQLResultSet(final Collection<String> columnNames, final 
Collection<LocalDataQueryResultRow> rows, final Statement statement) {
+        this.columnNames = new ArrayList<>(columnNames);
+        this.rows = rows.iterator();
+        this.statement = statement;
+    }
+    
+    @Override
+    public boolean isClosed() {
+        return closed;
+    }
+    
+    @Override
+    public boolean next() {
+        if (closed || !rows.hasNext()) {
+            currentRow = null;
+            return false;
+        }
+        currentRow = rows.next();
+        return true;
+    }
+    
+    @Override
+    public void close() {
+        closed = true;
+    }
+    
+    @Override
+    public ResultSetMetaData getMetaData() {
+        checkState();
+        return new DistSQLResultSetMetaData(columnNames);
+    }
+    
+    @Override
+    public boolean wasNull() {
+        checkState();
+        return lastReadWasNull;
+    }
+    
+    @Override
+    public String getString(final int columnIndex) {
+        checkStateForGetData();
+        Object value = currentRow.getCell(columnIndex);
+        lastReadWasNull = null == value;
+        return null == value ? null : value.toString();
+    }
+    
+    @Override
+    public String getString(final String columnLabel) {
+        return getString(findColumn(columnLabel));
+    }
+    
+    @Override
+    public String getNString(final int columnIndex) {
+        return getString(columnIndex);
+    }
+    
+    @Override
+    public String getNString(final String columnLabel) {
+        return getString(columnLabel);
+    }
+    
+    @Override
+    public byte getByte(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Byte.parseByte(value);
+    }
+    
+    @Override
+    public byte getByte(final String columnLabel) {
+        return getByte(findColumn(columnLabel));
+    }
+    
+    @Override
+    public short getShort(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Short.parseShort(value);

Review Comment:
   Potential uncaught 'java.lang.NumberFormatException'.
   ```suggestion
           if (null == value) {
               return 0;
           }
           try {
               return Short.parseShort(value);
           } catch (NumberFormatException ex) {
               throw new IllegalArgumentException("Value for column index " + 
columnIndex + " is not a valid short: " + value, ex);
           }
   ```



##########
jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/distsql/DistSQLResultSet.java:
##########
@@ -0,0 +1,270 @@
+/*
+ * 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.driver.executor.engine.distsql;
+
+import com.google.common.base.Preconditions;
+import 
org.apache.shardingsphere.driver.jdbc.unsupported.AbstractUnsupportedGeneratedKeysResultSet;
+import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.nio.charset.StandardCharsets;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * DistSQL result set.
+ */
+public final class DistSQLResultSet extends 
AbstractUnsupportedGeneratedKeysResultSet {
+    
+    private final List<String> columnNames;
+    
+    private final Iterator<LocalDataQueryResultRow> rows;
+    
+    private final Statement statement;
+    
+    private LocalDataQueryResultRow currentRow;
+    
+    private boolean closed;
+    
+    private boolean lastReadWasNull;
+    
+    public DistSQLResultSet(final Collection<String> columnNames, final 
Collection<LocalDataQueryResultRow> rows, final Statement statement) {
+        this.columnNames = new ArrayList<>(columnNames);
+        this.rows = rows.iterator();
+        this.statement = statement;
+    }
+    
+    @Override
+    public boolean isClosed() {
+        return closed;
+    }
+    
+    @Override
+    public boolean next() {
+        if (closed || !rows.hasNext()) {
+            currentRow = null;
+            return false;
+        }
+        currentRow = rows.next();
+        return true;
+    }
+    
+    @Override
+    public void close() {
+        closed = true;
+    }
+    
+    @Override
+    public ResultSetMetaData getMetaData() {
+        checkState();
+        return new DistSQLResultSetMetaData(columnNames);
+    }
+    
+    @Override
+    public boolean wasNull() {
+        checkState();
+        return lastReadWasNull;
+    }
+    
+    @Override
+    public String getString(final int columnIndex) {
+        checkStateForGetData();
+        Object value = currentRow.getCell(columnIndex);
+        lastReadWasNull = null == value;
+        return null == value ? null : value.toString();
+    }
+    
+    @Override
+    public String getString(final String columnLabel) {
+        return getString(findColumn(columnLabel));
+    }
+    
+    @Override
+    public String getNString(final int columnIndex) {
+        return getString(columnIndex);
+    }
+    
+    @Override
+    public String getNString(final String columnLabel) {
+        return getString(columnLabel);
+    }
+    
+    @Override
+    public byte getByte(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Byte.parseByte(value);
+    }
+    
+    @Override
+    public byte getByte(final String columnLabel) {
+        return getByte(findColumn(columnLabel));
+    }
+    
+    @Override
+    public short getShort(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Short.parseShort(value);
+    }
+    
+    @Override
+    public short getShort(final String columnLabel) {
+        return getShort(findColumn(columnLabel));
+    }
+    
+    @Override
+    public int getInt(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Integer.parseInt(value);
+    }
+    
+    @Override
+    public int getInt(final String columnLabel) {
+        return getInt(findColumn(columnLabel));
+    }
+    
+    @Override
+    public long getLong(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0L : Long.parseLong(value);
+    }
+    
+    @Override
+    public long getLong(final String columnLabel) {
+        return getLong(findColumn(columnLabel));
+    }
+    
+    @Override
+    public float getFloat(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0F : Float.parseFloat(value);
+    }
+    
+    @Override
+    public float getFloat(final String columnLabel) {
+        return getFloat(findColumn(columnLabel));
+    }
+    
+    @Override
+    public double getDouble(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0D : Double.parseDouble(value);
+    }
+    
+    @Override
+    public double getDouble(final String columnLabel) {
+        return getDouble(findColumn(columnLabel));
+    }
+    
+    @Override
+    public BigDecimal getBigDecimal(final int columnIndex, final int scale) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? null : new BigDecimal(value).setScale(scale, 
RoundingMode.HALF_UP);
+    }
+    
+    @Override
+    public BigDecimal getBigDecimal(final String columnLabel, final int scale) 
{
+        return getBigDecimal(findColumn(columnLabel), scale);
+    }
+    
+    @Override
+    public BigDecimal getBigDecimal(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? null : new BigDecimal(value);
+    }
+    
+    @Override
+    public BigDecimal getBigDecimal(final String columnLabel) {
+        return getBigDecimal(findColumn(columnLabel));
+    }
+    
+    @Override
+    public byte[] getBytes(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? null : value.getBytes(StandardCharsets.UTF_8);
+    }

Review Comment:
   The numeric getter methods (getByte, getShort, getInt, getLong, getFloat, 
getDouble, getBigDecimal) and getBytes are calling checkStateForGetData() and 
then calling getString(), which also calls checkStateForGetData(). This results 
in redundant state checks. Additionally, getString() updates the 
lastReadWasNull field, which means the wasNull() state is affected by the 
internal getString() call rather than the actual getter method being used. The 
checkStateForGetData() call should be removed from these methods since 
getString() already performs the check.



##########
docs/document/content/user-manual/shardingsphere-jdbc/distsql/_index.cn.md:
##########
@@ -0,0 +1,120 @@
++++
+title = "DistSQL"
+weight = 6
+chapter = true
++++
+
+# 背景信息
+
+当前可以通过 ShardingSphere JDBC DataSource 执行 DistSQL,以动态修改 ShardingSphere 配置。
+
+# 配置示例
+
+## 前提条件
+
+在业务项目引入如下依赖,
+
+```xml
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-jdbc-dialect-mysql</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-data-source-pool-hikari</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-infra-url-classpath</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-standalone-mode-repository-memory</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-sharding-core</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-authority-simple</artifactId>
+    <version>${shardingsphere.version}</version>
+</dependency>
+<dependency>
+    <groupId>com.h2database</groupId>
+    <artifactId>h2</artifactId>
+    <version>2.2.224</version>
+</dependency>
+```
+
+在业务项目的 classpath 上编写 ShardingSphere 数据源的配置文件 `demo.yaml`,
+
+```yaml
+props:
+  sql-show: false
+```
+
+## 享受集成
+
+创建 ShardingSphere 的数据源以享受集成,
+
+```java
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+public class ExampleUtils {
+    void test() throws SQLException {

Review Comment:
   The class name ExampleUtils with a test() method is not a conventional 
naming pattern for example code. The method should typically be named main() or 
have a more descriptive name that indicates what it demonstrates. Consider 
renaming the class to something like DistSQLExample and the method to 
demonstrateDistSQLUsage() or similar.
   ```suggestion
   public class DistSQLExample {
       void demonstrateDistSQLUsage() throws SQLException {
   ```



##########
test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/features/ShardingTest.java:
##########
@@ -38,12 +41,32 @@ void afterEach() throws SQLException {
         ResourceUtils.closeJdbcDataSource(logicDataSource);
     }
     
+    /**
+     * `groovy.lang.Closure` related classes are not available on GraalVM 
Native Image.
+     * This CLASS_BASE algorithm class is designed to emulate INLINE's 
`ds_${user_id % 2}`.

Review Comment:
   The JavaDoc comment states "This CLASS_BASE algorithm" but the actual type 
name used in the code is "class_based". The comment should use "CLASS_BASED" to 
match the actual constant name or algorithm type name used in the 
implementation.
   ```suggestion
        * This CLASS_BASED algorithm class is designed to emulate INLINE's 
`ds_${user_id % 2}`.
   ```



##########
jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/distsql/DistSQLResultSet.java:
##########
@@ -0,0 +1,270 @@
+/*
+ * 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.driver.executor.engine.distsql;
+
+import com.google.common.base.Preconditions;
+import 
org.apache.shardingsphere.driver.jdbc.unsupported.AbstractUnsupportedGeneratedKeysResultSet;
+import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.nio.charset.StandardCharsets;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * DistSQL result set.
+ */
+public final class DistSQLResultSet extends 
AbstractUnsupportedGeneratedKeysResultSet {
+    
+    private final List<String> columnNames;
+    
+    private final Iterator<LocalDataQueryResultRow> rows;
+    
+    private final Statement statement;
+    
+    private LocalDataQueryResultRow currentRow;
+    
+    private boolean closed;
+    
+    private boolean lastReadWasNull;
+    
+    public DistSQLResultSet(final Collection<String> columnNames, final 
Collection<LocalDataQueryResultRow> rows, final Statement statement) {
+        this.columnNames = new ArrayList<>(columnNames);
+        this.rows = rows.iterator();
+        this.statement = statement;
+    }
+    
+    @Override
+    public boolean isClosed() {
+        return closed;
+    }
+    
+    @Override
+    public boolean next() {
+        if (closed || !rows.hasNext()) {
+            currentRow = null;
+            return false;
+        }
+        currentRow = rows.next();
+        return true;
+    }
+    
+    @Override
+    public void close() {
+        closed = true;
+    }
+    
+    @Override
+    public ResultSetMetaData getMetaData() {
+        checkState();
+        return new DistSQLResultSetMetaData(columnNames);
+    }
+    
+    @Override
+    public boolean wasNull() {
+        checkState();
+        return lastReadWasNull;
+    }
+    
+    @Override
+    public String getString(final int columnIndex) {
+        checkStateForGetData();
+        Object value = currentRow.getCell(columnIndex);
+        lastReadWasNull = null == value;
+        return null == value ? null : value.toString();
+    }
+    
+    @Override
+    public String getString(final String columnLabel) {
+        return getString(findColumn(columnLabel));
+    }
+    
+    @Override
+    public String getNString(final int columnIndex) {
+        return getString(columnIndex);
+    }
+    
+    @Override
+    public String getNString(final String columnLabel) {
+        return getString(columnLabel);
+    }
+    
+    @Override
+    public byte getByte(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Byte.parseByte(value);
+    }
+    
+    @Override
+    public byte getByte(final String columnLabel) {
+        return getByte(findColumn(columnLabel));
+    }
+    
+    @Override
+    public short getShort(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Short.parseShort(value);
+    }
+    
+    @Override
+    public short getShort(final String columnLabel) {
+        return getShort(findColumn(columnLabel));
+    }
+    
+    @Override
+    public int getInt(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0 : Integer.parseInt(value);
+    }
+    
+    @Override
+    public int getInt(final String columnLabel) {
+        return getInt(findColumn(columnLabel));
+    }
+    
+    @Override
+    public long getLong(final int columnIndex) {
+        checkStateForGetData();
+        String value = getString(columnIndex);
+        return null == value ? 0L : Long.parseLong(value);

Review Comment:
   Potential uncaught 'java.lang.NumberFormatException'.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to