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]