This is an automated email from the ASF dual-hosted git repository.
duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 828419698c1 Fix sonar issues on Reduce the number of conditional
operators (#25991)
828419698c1 is described below
commit 828419698c1c38f830663f3411ac8c8305d3e792
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Jun 1 18:36:05 2023 +0800
Fix sonar issues on Reduce the number of conditional operators (#25991)
* Fix sonar issue on ShowShardingTableRulesUsedAlgorithmExecutor
* Fix sonar issue on DropBroadcastTableRuleStatementUpdater
* Fix sonar issue on DropDefaultStrategyStatementUpdater
* Fix sonar issue on DropShardingTableRuleStatementUpdater
* Fix sonar issue on MemoryMergedResult
* Fix sonar issue on ShardingSpherePreparedStatement
* Fix sonar issue on ShardingSphereStatement
* Fix sonar issue on PostgreSQLColumnPropertiesAppender
* Fix sonar issue on SQLFederationResultSet
* Fix sonar issue on MetaDataChangedWatcher
* Fix sonar issue on JDBCRepositorySQLLoader
* Fix sonar issue on MySQLFormatVisitor
* Fix sonar issue on ReadOnlyProxyState and UnavailableProxyState
* Fix sonar issue on MySQLSetCharsetExecutor
* Fix sonar issue on PostgreSQLCharacterSets
* Fix sonar issue on MySQLComQueryPacketExecutor
* Add SQLLineComment
* Fix code format
* Fix code format
---
...howShardingTableRulesUsedAlgorithmExecutor.java | 30 ++++++++++--
.../DropBroadcastTableRuleStatementUpdater.java | 11 ++++-
.../DropDefaultStrategyStatementUpdater.java | 11 ++++-
.../DropShardingTableRuleStatementUpdater.java | 11 ++++-
.../result/impl/memory/MemoryMergedResult.java | 8 +++-
.../jdbc/adapter/AbstractStatementAdapter.java | 55 +++++++++++++++-------
.../statement/ShardingSpherePreparedStatement.java | 16 +------
.../core/statement/ShardingSphereStatement.java | 16 +------
.../PostgreSQLColumnPropertiesAppender.java | 10 ++--
.../advanced/resultset/SQLFederationResultSet.java | 9 ++--
.../metadata/watcher/MetaDataChangedWatcher.java | 12 ++++-
.../jdbc/sql/JDBCRepositorySQLLoader.java | 21 ++-------
.../mysql/visitor/format/MySQLFormatVisitor.java | 18 +++++--
.../parser/sql/common/enums/QuoteCharacter.java | 10 ++++
.../sql/common/enums/QuoteCharacterTest.java | 12 +++++
.../handler/ProxyBackendHandlerFactory.java | 2 +-
.../backend/state/{spi => }/ProxyClusterState.java | 2 +-
.../state/SupportedSQLStatementJudgeEngine.java | 54 +++++++++++++++++++++
.../backend/state/impl/ReadOnlyProxyState.java | 24 ++++++----
.../backend/state/impl/UnavailableProxyState.java | 26 ++++++----
...ngsphere.proxy.backend.state.ProxyClusterState} | 0
.../SupportedSQLStatementJudgeEngineTest.java | 53 +++++++++++++++++++++
.../admin/executor/MySQLSetCharsetExecutor.java | 3 +-
.../handler/admin/PostgreSQLCharacterSets.java | 4 +-
.../text/query/MySQLComQueryPacketExecutor.java | 11 ++++-
.../loader/DefaultExternalTestParameterLoader.java | 6 +--
.../loader/ExternalMySQLTestParameterLoader.java | 6 +--
.../sql/parser/external/loader/SQLLineComment.java | 26 ++++++----
28 files changed, 339 insertions(+), 128 deletions(-)
diff --git
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/query/ShowShardingTableRulesUsedAlgorithmExecutor.java
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/query/ShowShardingTableRulesUsedAlgorithmExecutor.java
index 8b47f2ee42b..67b5d4fbb76 100644
---
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/query/ShowShardingTableRulesUsedAlgorithmExecutor.java
+++
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/query/ShowShardingTableRulesUsedAlgorithmExecutor.java
@@ -21,6 +21,7 @@ import
org.apache.shardingsphere.distsql.handler.query.RQLExecutor;
import
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
+import
org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import
org.apache.shardingsphere.sharding.distsql.parser.statement.ShowShardingTableRulesUsedAlgorithmStatement;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
@@ -53,10 +54,7 @@ public final class
ShowShardingTableRulesUsedAlgorithmExecutor implements RQLExe
boolean matchDefaultTableShardingStrategy = null !=
config.getDefaultTableShardingStrategy()
&&
algorithmName.equals(config.getDefaultTableShardingStrategy().getShardingAlgorithmName());
config.getTables().forEach(each -> {
- if (null == each.getDatabaseShardingStrategy() &&
matchDefaultDatabaseShardingStrategy
- || null != each.getDatabaseShardingStrategy() &&
algorithmName.equals(each.getDatabaseShardingStrategy().getShardingAlgorithmName())
- || null == each.getTableShardingStrategy() &&
matchDefaultTableShardingStrategy
- || null != each.getTableShardingStrategy() &&
algorithmName.equals(each.getTableShardingStrategy().getShardingAlgorithmName()))
{
+ if (isMatchDatabaseShardingStrategy(each, algorithmName,
matchDefaultDatabaseShardingStrategy) || isMatchTableShardingStrategy(each,
algorithmName, matchDefaultTableShardingStrategy)) {
result.add(new LocalDataQueryResultRow("table",
each.getLogicTable()));
}
});
@@ -67,6 +65,30 @@ public final class
ShowShardingTableRulesUsedAlgorithmExecutor implements RQLExe
});
}
+ private boolean isMatchDatabaseShardingStrategy(final
ShardingTableRuleConfiguration tableRuleConfig, final String algorithmName,
final boolean matchDefaultDatabaseShardingStrategy) {
+ return isMatchDatabaseShardingStrategy(tableRuleConfig, algorithmName)
|| isMatchDefaultDatabaseShardingStrategy(tableRuleConfig,
matchDefaultDatabaseShardingStrategy);
+ }
+
+ private boolean isMatchDatabaseShardingStrategy(final
ShardingTableRuleConfiguration tableRuleConfig, final String algorithmName) {
+ return null != tableRuleConfig.getDatabaseShardingStrategy() &&
algorithmName.equals(tableRuleConfig.getDatabaseShardingStrategy().getShardingAlgorithmName());
+ }
+
+ private boolean isMatchDefaultDatabaseShardingStrategy(final
ShardingTableRuleConfiguration tableRuleConfig, final boolean
matchDefaultDatabaseShardingStrategy) {
+ return null == tableRuleConfig.getDatabaseShardingStrategy() &&
matchDefaultDatabaseShardingStrategy;
+ }
+
+ private boolean isMatchTableShardingStrategy(final
ShardingTableRuleConfiguration tableRuleConfig, final String algorithmName,
final boolean matchDefaultTableShardingStrategy) {
+ return isMatchTableShardingStrategy(tableRuleConfig, algorithmName) ||
isMatchDefaultTableShardingStrategy(tableRuleConfig,
matchDefaultTableShardingStrategy);
+ }
+
+ private boolean isMatchTableShardingStrategy(final
ShardingTableRuleConfiguration tableRuleConfig, final String algorithmName) {
+ return null != tableRuleConfig.getTableShardingStrategy() &&
algorithmName.equals(tableRuleConfig.getTableShardingStrategy().getShardingAlgorithmName());
+ }
+
+ private boolean isMatchDefaultTableShardingStrategy(final
ShardingTableRuleConfiguration tableRuleConfig, final boolean
matchDefaultTableShardingStrategy) {
+ return null == tableRuleConfig.getTableShardingStrategy() &&
matchDefaultTableShardingStrategy;
+ }
+
@Override
public Collection<String> getColumnNames() {
return Arrays.asList("type", "name");
diff --git
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropBroadcastTableRuleStatementUpdater.java
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropBroadcastTableRuleStatementUpdater.java
index 34675e52679..9c23a67c305 100644
---
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropBroadcastTableRuleStatementUpdater.java
+++
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropBroadcastTableRuleStatementUpdater.java
@@ -68,8 +68,15 @@ public final class DropBroadcastTableRuleStatementUpdater
implements RuleDefinit
@Override
public boolean updateCurrentRuleConfiguration(final
DropBroadcastTableRuleStatement sqlStatement, final ShardingRuleConfiguration
currentRuleConfig) {
currentRuleConfig.getBroadcastTables().removeIf(each ->
containsIgnoreCase(sqlStatement.getTables(), each));
- return currentRuleConfig.getTables().isEmpty() &&
currentRuleConfig.getAutoTables().isEmpty() &&
currentRuleConfig.getBroadcastTables().isEmpty()
- && null ==
currentRuleConfig.getDefaultDatabaseShardingStrategy() && null ==
currentRuleConfig.getDefaultTableShardingStrategy();
+ return isEmptyShardingTables(currentRuleConfig) &&
currentRuleConfig.getBroadcastTables().isEmpty() &&
isEmptyShardingStrategy(currentRuleConfig);
+ }
+
+ private boolean isEmptyShardingTables(final ShardingRuleConfiguration
currentRuleConfig) {
+ return currentRuleConfig.getTables().isEmpty() &&
currentRuleConfig.getAutoTables().isEmpty();
+ }
+
+ private boolean isEmptyShardingStrategy(final ShardingRuleConfiguration
currentRuleConfig) {
+ return null == currentRuleConfig.getDefaultDatabaseShardingStrategy()
&& null == currentRuleConfig.getDefaultTableShardingStrategy();
}
@Override
diff --git
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropDefaultStrategyStatementUpdater.java
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropDefaultStrategyStatementUpdater.java
index deae1b60465..7a8b203a17d 100644
---
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropDefaultStrategyStatementUpdater.java
+++
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropDefaultStrategyStatementUpdater.java
@@ -80,8 +80,15 @@ public final class DropDefaultStrategyStatementUpdater
implements RuleDefinition
currentRuleConfig.setDefaultDatabaseShardingStrategy(null);
}
UnusedAlgorithmFinder.find(currentRuleConfig).forEach(each ->
currentRuleConfig.getShardingAlgorithms().remove(each));
- return currentRuleConfig.getTables().isEmpty() &&
currentRuleConfig.getAutoTables().isEmpty() &&
currentRuleConfig.getBroadcastTables().isEmpty()
- && null ==
currentRuleConfig.getDefaultDatabaseShardingStrategy() && null ==
currentRuleConfig.getDefaultTableShardingStrategy();
+ return isEmptyShardingTables(currentRuleConfig) &&
currentRuleConfig.getBroadcastTables().isEmpty() &&
isEmptyShardingStrategy(currentRuleConfig);
+ }
+
+ private boolean isEmptyShardingTables(final ShardingRuleConfiguration
currentRuleConfig) {
+ return currentRuleConfig.getTables().isEmpty() &&
currentRuleConfig.getAutoTables().isEmpty();
+ }
+
+ private boolean isEmptyShardingStrategy(final ShardingRuleConfiguration
currentRuleConfig) {
+ return null == currentRuleConfig.getDefaultDatabaseShardingStrategy()
&& null == currentRuleConfig.getDefaultTableShardingStrategy();
}
@Override
diff --git
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropShardingTableRuleStatementUpdater.java
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropShardingTableRuleStatementUpdater.java
index e75d666d357..69c30022cd1 100644
---
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropShardingTableRuleStatementUpdater.java
+++
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/update/DropShardingTableRuleStatementUpdater.java
@@ -112,8 +112,7 @@ public final class DropShardingTableRuleStatementUpdater
implements RuleDefiniti
UnusedAlgorithmFinder.find(currentRuleConfig).forEach(each ->
currentRuleConfig.getShardingAlgorithms().remove(each));
dropUnusedKeyGenerator(currentRuleConfig);
dropUnusedAuditor(currentRuleConfig);
- return currentRuleConfig.getTables().isEmpty() &&
currentRuleConfig.getAutoTables().isEmpty() &&
currentRuleConfig.getBroadcastTables().isEmpty()
- && null ==
currentRuleConfig.getDefaultDatabaseShardingStrategy() && null ==
currentRuleConfig.getDefaultTableShardingStrategy();
+ return isEmptyShardingTables(currentRuleConfig) &&
currentRuleConfig.getBroadcastTables().isEmpty() &&
isEmptyShardingStrategy(currentRuleConfig);
}
private void dropShardingTable(final ShardingRuleConfiguration
currentRuleConfig, final String tableName) {
@@ -149,6 +148,14 @@ public final class DropShardingTableRuleStatementUpdater
implements RuleDefiniti
unusedAuditors.forEach(each ->
currentRuleConfig.getAuditors().remove(each));
}
+ private boolean isEmptyShardingTables(final ShardingRuleConfiguration
currentRuleConfig) {
+ return currentRuleConfig.getTables().isEmpty() &&
currentRuleConfig.getAutoTables().isEmpty();
+ }
+
+ private boolean isEmptyShardingStrategy(final ShardingRuleConfiguration
currentRuleConfig) {
+ return null == currentRuleConfig.getDefaultDatabaseShardingStrategy()
&& null == currentRuleConfig.getDefaultTableShardingStrategy();
+ }
+
@Override
public Class<ShardingRuleConfiguration> getRuleConfigurationClass() {
return ShardingRuleConfiguration.class;
diff --git
a/infra/merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
b/infra/merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
index d0d874db5a9..ff3b0b06bd3 100644
---
a/infra/merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
+++
b/infra/merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
@@ -31,7 +31,10 @@ import java.sql.Clob;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLXML;
+import java.util.Arrays;
import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -42,6 +45,8 @@ import java.util.List;
*/
public abstract class MemoryMergedResult<T extends ShardingSphereRule>
implements MergedResult {
+ private static final Collection<Class<?>> INVALID_MEMORY_TYPES = new
HashSet<>(Arrays.asList(Blob.class, Clob.class, Reader.class,
InputStream.class, SQLXML.class));
+
private final Iterator<MemoryQueryResultRow> memoryResultSetRows;
private MemoryQueryResultRow currentResultSetRow;
@@ -69,8 +74,7 @@ public abstract class MemoryMergedResult<T extends
ShardingSphereRule> implement
@Override
public final Object getValue(final int columnIndex, final Class<?> type)
throws SQLException {
- ShardingSpherePreconditions.checkState(Blob.class != type &&
Clob.class != type && Reader.class != type && InputStream.class != type &&
SQLXML.class != type,
- () -> new SQLFeatureNotSupportedException(String.format("Get
value from `%s`", type.getName())));
+
ShardingSpherePreconditions.checkState(!INVALID_MEMORY_TYPES.contains(type), ()
-> new SQLFeatureNotSupportedException(String.format("Get value from `%s`",
type.getName())));
Object result = currentResultSetRow.getCell(columnIndex);
wasNull = null == result;
return result;
diff --git
a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/AbstractStatementAdapter.java
b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/AbstractStatementAdapter.java
index e4df3748b22..c82c3ea0d40 100644
---
a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/AbstractStatementAdapter.java
+++
b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/AbstractStatementAdapter.java
@@ -26,7 +26,13 @@ import
org.apache.shardingsphere.driver.jdbc.core.statement.StatementManager;
import
org.apache.shardingsphere.driver.jdbc.unsupported.AbstractUnsupportedOperationStatement;
import org.apache.shardingsphere.infra.database.type.DatabaseType;
import
org.apache.shardingsphere.infra.database.type.SchemaSupportedDatabaseType;
+import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.transaction.ConnectionTransaction;
+import org.apache.shardingsphere.transaction.api.TransactionType;
import java.sql.SQLException;
import java.sql.SQLWarning;
@@ -50,6 +56,38 @@ public abstract class AbstractStatementAdapter extends
AbstractUnsupportedOperat
private boolean closed;
+ protected final boolean isNeedImplicitCommitTransaction(final
ShardingSphereConnection connection, final ExecutionContext executionContext) {
+ return isInDistributedTransaction(connection) &&
isModifiedSQL(executionContext) && executionContext.getExecutionUnits().size()
> 1;
+ }
+
+ private boolean isInDistributedTransaction(final ShardingSphereConnection
connection) {
+ ConnectionTransaction connectionTransaction =
connection.getDatabaseConnectionManager().getConnectionTransaction();
+ boolean isInTransaction =
connection.getDatabaseConnectionManager().getConnectionContext().getTransactionContext().isInTransaction();
+ return
TransactionType.isDistributedTransaction(connectionTransaction.getTransactionType())
&& !isInTransaction;
+ }
+
+ private boolean isModifiedSQL(final ExecutionContext executionContext) {
+ SQLStatement sqlStatement =
executionContext.getSqlStatementContext().getSqlStatement();
+ return sqlStatement instanceof DMLStatement && !(sqlStatement
instanceof SelectStatement);
+ }
+
+ protected final void handleExceptionInTransaction(final
ShardingSphereConnection connection, final MetaDataContexts metaDataContexts) {
+ if
(connection.getDatabaseConnectionManager().getConnectionTransaction().isInTransaction())
{
+ DatabaseType databaseType =
metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName()).getProtocolType();
+ if (databaseType instanceof SchemaSupportedDatabaseType) {
+
connection.getDatabaseConnectionManager().getConnectionTransaction().setRollbackOnly(true);
+ }
+ }
+ }
+
+ protected abstract boolean isAccumulate();
+
+ protected abstract Collection<? extends Statement> getRoutedStatements();
+
+ protected abstract DriverExecutor getExecutor();
+
+ protected abstract StatementManager getStatementManager();
+
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public final void setPoolable(final boolean poolable) throws SQLException {
@@ -191,21 +229,4 @@ public abstract class AbstractStatementAdapter extends
AbstractUnsupportedOperat
getRoutedStatements().clear();
}
}
-
- protected final void handleExceptionInTransaction(final
ShardingSphereConnection connection, final MetaDataContexts metaDataContexts) {
- if
(connection.getDatabaseConnectionManager().getConnectionTransaction().isInTransaction())
{
- DatabaseType databaseType =
metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName()).getProtocolType();
- if (databaseType instanceof SchemaSupportedDatabaseType) {
-
connection.getDatabaseConnectionManager().getConnectionTransaction().setRollbackOnly(true);
- }
- }
- }
-
- protected abstract boolean isAccumulate();
-
- protected abstract Collection<? extends Statement> getRoutedStatements();
-
- protected abstract DriverExecutor getExecutor();
-
- protected abstract StatementManager getStatementManager();
}
diff --git
a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
index 49e6dbea5f4..596301cd447 100644
---
a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
+++
b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
@@ -88,14 +88,10 @@ import
org.apache.shardingsphere.mode.metadata.MetaDataContexts;
import org.apache.shardingsphere.parser.rule.SQLParserRule;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dal.DALStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import
org.apache.shardingsphere.sqlfederation.spi.SQLFederationExecutorContext;
import org.apache.shardingsphere.traffic.engine.TrafficEngine;
import
org.apache.shardingsphere.traffic.exception.metadata.EmptyTrafficExecutionUnitException;
import org.apache.shardingsphere.traffic.rule.TrafficRule;
-import org.apache.shardingsphere.transaction.ConnectionTransaction;
-import org.apache.shardingsphere.transaction.api.TransactionType;
import java.sql.Connection;
import java.sql.ParameterMetaData;
@@ -374,7 +370,7 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
Collection<ExecuteResult> executeResults =
executor.getRawExecutor().execute(createRawExecutionGroupContext(),
executionContext.getQueryContext(), new RawSQLExecutorCallback());
return accumulate(executeResults);
}
- return isNeedImplicitCommitTransaction(executionContext) ?
executeUpdateWithImplicitCommitTransaction() : useDriverToExecuteUpdate();
+ return isNeedImplicitCommitTransaction(connection,
executionContext) ? executeUpdateWithImplicitCommitTransaction() :
useDriverToExecuteUpdate();
// CHECKSTYLE:OFF
} catch (final RuntimeException ex) {
// CHECKSTYLE:ON
@@ -443,7 +439,7 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
Collection<ExecuteResult> executeResults =
executor.getRawExecutor().execute(createRawExecutionGroupContext(),
executionContext.getQueryContext(), new RawSQLExecutorCallback());
return executeResults.iterator().next() instanceof QueryResult;
}
- return isNeedImplicitCommitTransaction(executionContext) ?
executeWithImplicitCommitTransaction() : useDriverToExecute();
+ return isNeedImplicitCommitTransaction(connection,
executionContext) ? executeWithImplicitCommitTransaction() :
useDriverToExecute();
// CHECKSTYLE:OFF
} catch (final RuntimeException ex) {
// CHECKSTYLE:ON
@@ -469,14 +465,6 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
.prepare(executionContext.getRouteContext(),
executionContext.getExecutionUnits(), new
ExecutionGroupReportContext(connection.getDatabaseName()));
}
- private boolean isNeedImplicitCommitTransaction(final ExecutionContext
executionContext) {
- ConnectionTransaction connectionTransaction =
connection.getDatabaseConnectionManager().getConnectionTransaction();
- boolean isInTransaction =
connection.getDatabaseConnectionManager().getConnectionContext().getTransactionContext().isInTransaction();
- SQLStatement sqlStatement =
executionContext.getSqlStatementContext().getSqlStatement();
- return
TransactionType.isDistributedTransaction(connectionTransaction.getTransactionType())
&& !isInTransaction && sqlStatement instanceof DMLStatement
- && !(sqlStatement instanceof SelectStatement) &&
executionContext.getExecutionUnits().size() > 1;
- }
-
private boolean executeWithImplicitCommitTransaction() throws SQLException
{
boolean result;
try {
diff --git
a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
index ab0dc1421ef..3b3ff67fda2 100644
---
a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
+++
b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
@@ -83,15 +83,11 @@ import
org.apache.shardingsphere.mode.metadata.MetaDataContexts;
import org.apache.shardingsphere.parser.rule.SQLParserRule;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dal.DALStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import
org.apache.shardingsphere.sqlfederation.spi.SQLFederationExecutorContext;
import org.apache.shardingsphere.traffic.engine.TrafficEngine;
import
org.apache.shardingsphere.traffic.exception.metadata.EmptyTrafficExecutionUnitException;
import org.apache.shardingsphere.traffic.executor.TrafficExecutorCallback;
import org.apache.shardingsphere.traffic.rule.TrafficRule;
-import org.apache.shardingsphere.transaction.ConnectionTransaction;
-import org.apache.shardingsphere.transaction.api.TransactionType;
import java.sql.Connection;
import java.sql.ResultSet;
@@ -340,7 +336,7 @@ public final class ShardingSphereStatement extends
AbstractStatementAdapter {
}
private int executeUpdate(final ExecuteUpdateCallback updateCallback,
final SQLStatementContext sqlStatementContext) throws SQLException {
- return isNeedImplicitCommitTransaction(executionContext) ?
executeUpdateWithImplicitCommitTransaction(updateCallback, sqlStatementContext)
+ return isNeedImplicitCommitTransaction(connection, executionContext) ?
executeUpdateWithImplicitCommitTransaction(updateCallback, sqlStatementContext)
: useDriverToExecuteUpdate(updateCallback,
sqlStatementContext);
}
@@ -480,7 +476,7 @@ public final class ShardingSphereStatement extends
AbstractStatementAdapter {
Collection<ExecuteResult> results =
executor.getRawExecutor().execute(createRawExecutionContext(),
executionContext.getQueryContext(), new RawSQLExecutorCallback());
return results.iterator().next() instanceof QueryResult;
}
- return isNeedImplicitCommitTransaction(executionContext) ?
executeWithImplicitCommitTransaction(executeCallback) :
useDriverToExecute(executeCallback);
+ return isNeedImplicitCommitTransaction(connection,
executionContext) ? executeWithImplicitCommitTransaction(executeCallback) :
useDriverToExecute(executeCallback);
} finally {
currentResultSet = null;
}
@@ -559,14 +555,6 @@ public final class ShardingSphereStatement extends
AbstractStatementAdapter {
.prepare(executionContext.getRouteContext(),
executionContext.getExecutionUnits(), new
ExecutionGroupReportContext(connection.getDatabaseName()));
}
- private boolean isNeedImplicitCommitTransaction(final ExecutionContext
executionContext) {
- ConnectionTransaction connectionTransaction =
connection.getDatabaseConnectionManager().getConnectionTransaction();
- boolean isInTransaction =
connection.getDatabaseConnectionManager().getConnectionContext().getTransactionContext().isInTransaction();
- SQLStatement sqlStatement =
executionContext.getSqlStatementContext().getSqlStatement();
- return
TransactionType.isDistributedTransaction(connectionTransaction.getTransactionType())
&& !isInTransaction && sqlStatement instanceof DMLStatement
- && !(sqlStatement instanceof SelectStatement) &&
executionContext.getExecutionUnits().size() > 1;
- }
-
private boolean executeWithImplicitCommitTransaction(final ExecuteCallback
callback) throws SQLException {
boolean result;
try {
diff --git
a/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/ddlgenerator/PostgreSQLColumnPropertiesAppender.java
b/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/ddlgenerator/PostgreSQLColumnPropertiesAppender.java
index b66f9e8158d..464d2d6bc9c 100644
---
a/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/ddlgenerator/PostgreSQLColumnPropertiesAppender.java
+++
b/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/ddlgenerator/PostgreSQLColumnPropertiesAppender.java
@@ -25,6 +25,7 @@ import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
@@ -37,6 +38,11 @@ import java.util.stream.Collectors;
*/
public final class PostgreSQLColumnPropertiesAppender extends
AbstractPostgreSQLDDLAdapter {
+ private static final Collection<String> TIME_TYPE_NAMES = new
HashSet<>(Arrays.asList(
+ "time", "timetz", "time without time zone", "time with time zone",
"timestamp", "timestamptz", "timestamp without time zone", "timestamp with time
zone"));
+
+ private static final Collection<String> BIT_TYPE_NAMES = new
HashSet<>(Arrays.asList("bit", "bit varying", "varbit"));
+
private static final Pattern LENGTH_PRECISION_PATTERN =
Pattern.compile("(\\d+),(\\d+)");
private static final Pattern LENGTH_PATTERN = Pattern.compile("(\\d+)");
@@ -262,9 +268,7 @@ public final class PostgreSQLColumnPropertiesAppender
extends AbstractPostgreSQL
int prec = (typmod - 4) & 0xffff;
result += String.valueOf(len);
result += "," + prec;
- } else if ("time".equals(name) || "timetz".equals(name) || "time
without time zone".equals(name) || "time with time zone".equals(name)
- || "timestamp".equals(name) || "timestamptz".equals(name) ||
"timestamp without time zone".equals(name) || "timestamp with time
zone".equals(name)
- || "bit".equals(name) || "bit varying".equals(name) ||
"varbit".equals(name)) {
+ } else if (TIME_TYPE_NAMES.contains(name) ||
BIT_TYPE_NAMES.contains(name)) {
int len = typmod;
result += String.valueOf(len);
} else if ("interval".equals(name)) {
diff --git
a/kernel/sql-federation/executor/advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/resultset/SQLFederationResultSet.java
b/kernel/sql-federation/executor/advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/resultset/SQLFederationResultSet.java
index 3fa7a90366d..2f8c24e7de6 100644
---
a/kernel/sql-federation/executor/advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/resultset/SQLFederationResultSet.java
+++
b/kernel/sql-federation/executor/advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/resultset/SQLFederationResultSet.java
@@ -46,8 +46,11 @@ import java.sql.SQLXML;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
+import java.util.Arrays;
import java.util.Calendar;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -62,6 +65,8 @@ public final class SQLFederationResultSet extends
AbstractUnsupportedOperationRe
private static final String BINARY = "Binary";
+ private static final Collection<Class<?>> INVALID_FEDERATION_TYPES = new
HashSet<>(Arrays.asList(Blob.class, Clob.class, Reader.class,
InputStream.class, SQLXML.class));
+
private final Enumerator<Object> enumerator;
private final Map<String, Integer> columnLabelAndIndexes;
@@ -467,9 +472,7 @@ public final class SQLFederationResultSet extends
AbstractUnsupportedOperationRe
}
private Object getValue(final int columnIndex, final Class<?> type) throws
SQLException {
- if (Blob.class == type || Clob.class == type || Reader.class == type
|| InputStream.class == type || SQLXML.class == type) {
- throw new SQLFeatureNotSupportedException(String.format("Get value
from `%s`", type.getName()));
- }
+
ShardingSpherePreconditions.checkState(!INVALID_FEDERATION_TYPES.contains(type),
() -> new SQLFeatureNotSupportedException(String.format("Get value from `%s`",
type.getName())));
Object result = currentRows[columnIndex - 1];
wasNull = null == result;
return result;
diff --git
a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/MetaDataChangedWatcher.java
b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/MetaDataChangedWatcher.java
index 7399d448716..54fbcc7cf91 100644
---
a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/MetaDataChangedWatcher.java
+++
b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/MetaDataChangedWatcher.java
@@ -95,12 +95,20 @@ public final class MetaDataChangedWatcher implements
GovernanceWatcher<Governanc
}
private boolean schemaMetaDataChanged(final DataChangedEvent event) {
+ if (Strings.isNullOrEmpty(event.getValue())) {
+ return false;
+ }
Optional<String> databaseName =
DatabaseMetaDataNode.getDatabaseNameByDatabasePath(event.getKey());
+ if (!databaseName.isPresent()) {
+ return false;
+ }
Optional<String> schemaName =
DatabaseMetaDataNode.getSchemaNameBySchemaPath(event.getKey());
+ if (!schemaName.isPresent()) {
+ return false;
+ }
Optional<String> tableName =
DatabaseMetaDataNode.getTableName(event.getKey());
Optional<String> viewName =
DatabaseMetaDataNode.getViewName(event.getKey());
- return databaseName.isPresent() && schemaName.isPresent() &&
!Strings.isNullOrEmpty(event.getValue())
- && (tableName.isPresent() &&
!SystemSchemaBuilderRule.isSystemTable(databaseName.get(), tableName.get()) ||
viewName.isPresent());
+ return tableName.isPresent() &&
!SystemSchemaBuilderRule.isSystemTable(databaseName.get(), tableName.get()) ||
viewName.isPresent();
}
private Optional<GovernanceEvent> createDatabaseChangedEvent(final
DataChangedEvent event) {
diff --git
a/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java
b/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java
index de891dc3af2..6794a0d7ad5 100644
---
a/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java
+++
b/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java
@@ -34,7 +34,10 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -49,15 +52,7 @@ public final class JDBCRepositorySQLLoader {
private static final String FILE_EXTENSION = ".xml";
- private static final String URL_PROTOCOL_JAR = "jar";
-
- private static final String URL_PROTOCOL_WAR = "war";
-
- private static final String URL_PROTOCOL_ZIP = "zip";
-
- private static final String URL_PROTOCOL_WSJAR = "wsjar";
-
- private static final String URL_PROTOCOL_VFSZIP = "vfszip";
+ private static final Collection<String> JAR_URL_PROTOCOLS = new
HashSet<>(Arrays.asList("jar", "war", "zip", "wsjar", "vfszip"));
/**
* Load JDBC repository SQL.
@@ -74,7 +69,7 @@ public final class JDBCRepositorySQLLoader {
JDBCRepositorySQL result = null;
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
- result = isJarURL(resource) ? loadFromJar(resource, type) :
loadFromDirectory(resource, type);
+ result = JAR_URL_PROTOCOLS.contains(resource.getProtocol()) ?
loadFromJar(resource, type) : loadFromDirectory(resource, type);
if (null != result && Objects.equals(result.isDefault(), false)) {
break;
}
@@ -82,12 +77,6 @@ public final class JDBCRepositorySQLLoader {
return result;
}
- private static boolean isJarURL(final URL url) {
- String protocol = url.getProtocol();
- return URL_PROTOCOL_JAR.equals(protocol) ||
URL_PROTOCOL_WAR.equals(protocol) || URL_PROTOCOL_ZIP.equals(protocol)
- || URL_PROTOCOL_VFSZIP.equals(protocol) ||
URL_PROTOCOL_WSJAR.equals(protocol);
- }
-
private static JDBCRepositorySQL loadFromDirectory(final URL url, final
String type) throws URISyntaxException, IOException {
final JDBCRepositorySQL[] result = new JDBCRepositorySQL[1];
Files.walkFileTree(Paths.get(url.toURI()), new
SimpleFileVisitor<Path>() {
diff --git
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/format/MySQLFormatVisitor.java
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/format/MySQLFormatVisitor.java
index dcae7187ab5..11f318615ce 100644
---
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/format/MySQLFormatVisitor.java
+++
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/format/MySQLFormatVisitor.java
@@ -17,6 +17,7 @@
package org.apache.shardingsphere.sql.parser.mysql.visitor.format;
+import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.antlr.v4.runtime.tree.TerminalNode;
@@ -70,6 +71,9 @@ import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.UserVar
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WhereClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WithClauseContext;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Properties;
/**
@@ -77,6 +81,9 @@ import java.util.Properties;
*/
public final class MySQLFormatVisitor extends
MySQLStatementBaseVisitor<String> implements SQLFormatVisitor {
+ private static final Collection<Class<? extends ParserRuleContext>>
DATA_TYPE_EXTRA_DESCRIPTION_CONTEXT_CLASSES = new HashSet<>(
+ Arrays.asList(FieldLengthContext.class, PrecisionContext.class,
StringListContext.class, TypeDatetimePrecisionContext.class));
+
private final StringBuilder formattedSQL = new StringBuilder(256);
private boolean upperCase = true;
@@ -642,7 +649,7 @@ public final class MySQLFormatVisitor extends
MySQLStatementBaseVisitor<String>
int childCount = ctx.getChildCount();
for (int i = 0; i < childCount; i++) {
ParseTree child = ctx.getChild(i);
- if (i != 0 && !(child instanceof FieldLengthContext || child
instanceof PrecisionContext || child instanceof StringListContext || child
instanceof TypeDatetimePrecisionContext)) {
+ if (0 != i &&
!DATA_TYPE_EXTRA_DESCRIPTION_CONTEXT_CLASSES.contains(child.getClass())) {
formatPrint(" ");
}
child.accept(this);
@@ -799,9 +806,12 @@ public final class MySQLFormatVisitor extends
MySQLStatementBaseVisitor<String>
String result = defaultResult();
int childCount = node.getChildCount();
for (int i = 0; i < childCount; i++) {
- if (i != 0 && !"(".equals(node.getChild(i - 1).getText()) &&
!".".equals(node.getChild(i - 1).getText())
- && !")".equals(node.getChild(i).getText()) &&
!"(".equals(node.getChild(i).getText()) &&
!".".equals(node.getChild(i).getText())) {
- formatPrint(" ");
+ if (0 != i) {
+ String previousText = node.getChild(i - 1).getText();
+ String text = node.getChild(i).getText();
+ if (!"(".equals(previousText) && !".".equals(previousText) &&
!")".equals(text) && !"(".equals(text) && !".".equals(text)) {
+ formatPrint(" ");
+ }
}
if (!shouldVisitNextChild(node, result)) {
break;
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacter.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacter.java
index 4646a7516e1..7ae5b7f8240 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacter.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacter.java
@@ -68,4 +68,14 @@ public enum QuoteCharacter {
public String wrap(final String value) {
return startDelimiter + value + endDelimiter;
}
+
+ /**
+ * Is wrapped by quote character.
+ *
+ * @param value value to be judged
+ * @return is wrapped or not
+ */
+ public boolean isWrapped(final String value) {
+ return value.startsWith(startDelimiter) &&
value.endsWith(endDelimiter);
+ }
}
diff --git
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacterTest.java
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacterTest.java
index c335679f818..7663ac6854f 100644
---
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacterTest.java
+++
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/enums/QuoteCharacterTest.java
@@ -21,6 +21,8 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
class QuoteCharacterTest {
@@ -63,4 +65,14 @@ class QuoteCharacterTest {
void assertWarp() {
assertThat(QuoteCharacter.BACK_QUOTE.wrap("test"), is("`test`"));
}
+
+ @Test
+ void assertIsWrapped() {
+ assertTrue(QuoteCharacter.SINGLE_QUOTE.isWrapped("'test'"));
+ }
+
+ @Test
+ void assertIsNotWrapped() {
+ assertFalse(QuoteCharacter.SINGLE_QUOTE.isWrapped("'test\""));
+ }
}
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
index 6db0b64d554..ce7847618a3 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
@@ -49,7 +49,7 @@ import
org.apache.shardingsphere.proxy.backend.handler.extra.ExtraProxyBackendHa
import org.apache.shardingsphere.proxy.backend.handler.skip.SkipBackendHandler;
import
org.apache.shardingsphere.proxy.backend.handler.transaction.TransactionBackendHandlerFactory;
import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.apache.shardingsphere.proxy.backend.state.spi.ProxyClusterState;
+import org.apache.shardingsphere.proxy.backend.state.ProxyClusterState;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dal.EmptyStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dal.FlushStatement;
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/spi/ProxyClusterState.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/ProxyClusterState.java
similarity index 95%
copy from
proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/spi/ProxyClusterState.java
copy to
proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/ProxyClusterState.java
index 175c9bb71de..c8c95858011 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/spi/ProxyClusterState.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/ProxyClusterState.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.state.spi;
+package org.apache.shardingsphere.proxy.backend.state;
import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPI;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/SupportedSQLStatementJudgeEngine.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/SupportedSQLStatementJudgeEngine.java
new file mode 100644
index 00000000000..38701c0b806
--- /dev/null
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/SupportedSQLStatementJudgeEngine.java
@@ -0,0 +1,54 @@
+/*
+ * 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.proxy.backend.state;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+
+import java.util.Collection;
+
+/**
+ * Supported SQL statement judge engine.
+ */
+@RequiredArgsConstructor
+public final class SupportedSQLStatementJudgeEngine {
+
+ private final Collection<Class<? extends SQLStatement>>
supportedSQLStatements;
+
+ private final Collection<Class<? extends SQLStatement>>
unsupportedSQLStatements;
+
+ /**
+ * Judge whether SQL statement is supported.
+ *
+ * @param sqlStatement SQL statement to be judged
+ * @return supported or not
+ */
+ public boolean isSupported(final SQLStatement sqlStatement) {
+ for (Class<? extends SQLStatement> each : supportedSQLStatements) {
+ if (each.isAssignableFrom(sqlStatement.getClass())) {
+ return true;
+ }
+ }
+ for (Class<? extends SQLStatement> each : unsupportedSQLStatements) {
+ if (each.isAssignableFrom(sqlStatement.getClass())) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/ReadOnlyProxyState.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/ReadOnlyProxyState.java
index 285e21a4039..5e20fcbdea6 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/ReadOnlyProxyState.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/ReadOnlyProxyState.java
@@ -20,29 +20,35 @@ package org.apache.shardingsphere.proxy.backend.state.impl;
import
org.apache.shardingsphere.distsql.parser.statement.ral.UpdatableRALStatement;
import
org.apache.shardingsphere.distsql.parser.statement.ral.updatable.UnlockClusterStatement;
import org.apache.shardingsphere.distsql.parser.statement.rdl.RDLStatement;
+import
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.proxy.backend.exception.ReadOnlyException;
-import org.apache.shardingsphere.proxy.backend.state.spi.ProxyClusterState;
+import org.apache.shardingsphere.proxy.backend.state.ProxyClusterState;
+import
org.apache.shardingsphere.proxy.backend.state.SupportedSQLStatementJudgeEngine;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
/**
* ReadOnly proxy state.
*/
public final class ReadOnlyProxyState implements ProxyClusterState {
+ private static final Collection<Class<? extends SQLStatement>>
SUPPORTED_SQL_STATEMENTS = Collections.singleton(UnlockClusterStatement.class);
+
+ private static final Collection<Class<? extends SQLStatement>>
UNSUPPORTED_SQL_STATEMENTS = Arrays.asList(
+ InsertStatement.class, UpdateStatement.class,
DeleteStatement.class, DDLStatement.class, UpdatableRALStatement.class,
RDLStatement.class);
+
+ private final SupportedSQLStatementJudgeEngine judgeEngine = new
SupportedSQLStatementJudgeEngine(SUPPORTED_SQL_STATEMENTS,
UNSUPPORTED_SQL_STATEMENTS);
+
@Override
public void check(final SQLStatement sqlStatement) {
- if (isUnsupportedStatement(sqlStatement)) {
- throw new ReadOnlyException();
- }
- }
-
- private boolean isUnsupportedStatement(final SQLStatement sqlStatement) {
- return sqlStatement instanceof InsertStatement || sqlStatement
instanceof UpdateStatement || sqlStatement instanceof DeleteStatement ||
sqlStatement instanceof DDLStatement
- || sqlStatement instanceof UpdatableRALStatement &&
!(sqlStatement instanceof UnlockClusterStatement) || sqlStatement instanceof
RDLStatement;
+
ShardingSpherePreconditions.checkState(judgeEngine.isSupported(sqlStatement),
ReadOnlyException::new);
}
@Override
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/UnavailableProxyState.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/UnavailableProxyState.java
index fdc55fdbcb6..ee91da17adb 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/UnavailableProxyState.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/impl/UnavailableProxyState.java
@@ -21,29 +21,35 @@ import
org.apache.shardingsphere.distsql.parser.statement.ral.QueryableRALStatem
import
org.apache.shardingsphere.distsql.parser.statement.ral.updatable.ImportMetaDataStatement;
import
org.apache.shardingsphere.distsql.parser.statement.ral.updatable.UnlockClusterStatement;
import org.apache.shardingsphere.distsql.parser.statement.rql.RQLStatement;
+import
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.proxy.backend.exception.UnavailableException;
-import org.apache.shardingsphere.proxy.backend.state.spi.ProxyClusterState;
+import org.apache.shardingsphere.proxy.backend.state.ProxyClusterState;
+import
org.apache.shardingsphere.proxy.backend.state.SupportedSQLStatementJudgeEngine;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dal.ShowStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLShowDatabasesStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLUseStatement;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
/**
* Unavailable proxy state.
*/
public final class UnavailableProxyState implements ProxyClusterState {
+ private static final Collection<Class<? extends SQLStatement>>
SUPPORTED_SQL_STATEMENTS = Arrays.asList(
+ ImportMetaDataStatement.class, ShowStatement.class,
QueryableRALStatement.class,
+ RQLStatement.class, UnlockClusterStatement.class,
MySQLShowDatabasesStatement.class, MySQLUseStatement.class);
+
+ private static final Collection<Class<? extends SQLStatement>>
UNSUPPORTED_SQL_STATEMENTS = Collections.singleton(SQLStatement.class);
+
+ private final SupportedSQLStatementJudgeEngine judgeEngine = new
SupportedSQLStatementJudgeEngine(SUPPORTED_SQL_STATEMENTS,
UNSUPPORTED_SQL_STATEMENTS);
+
@Override
public void check(final SQLStatement sqlStatement) {
- if (isSupportedStatement(sqlStatement)) {
- return;
- }
- throw new UnavailableException();
- }
-
- private boolean isSupportedStatement(final SQLStatement sqlStatement) {
- return sqlStatement instanceof ImportMetaDataStatement || sqlStatement
instanceof ShowStatement || sqlStatement instanceof QueryableRALStatement ||
sqlStatement instanceof RQLStatement
- || sqlStatement instanceof UnlockClusterStatement ||
sqlStatement instanceof MySQLShowDatabasesStatement || sqlStatement instanceof
MySQLUseStatement;
+
ShardingSpherePreconditions.checkState(judgeEngine.isSupported(sqlStatement),
UnavailableException::new);
}
@Override
diff --git
a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.state.spi.ProxyClusterState
b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.state.ProxyClusterState
similarity index 100%
rename from
proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.state.spi.ProxyClusterState
rename to
proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.state.ProxyClusterState
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/state/SupportedSQLStatementJudgeEngineTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/state/SupportedSQLStatementJudgeEngineTest.java
new file mode 100644
index 00000000000..c166c2e7341
--- /dev/null
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/state/SupportedSQLStatementJudgeEngineTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.proxy.backend.state;
+
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+
+class SupportedSQLStatementJudgeEngineTest {
+
+ @Test
+ void assertIsSupportedWithInSupportedList() {
+ assertTrue(new
SupportedSQLStatementJudgeEngine(Collections.singleton(SelectStatement.class),
Collections.emptyList()).isSupported(mock(SelectStatement.class)));
+ }
+
+ @Test
+ void assertIsNotSupportedWithInUnsupportedList() {
+ assertFalse(new
SupportedSQLStatementJudgeEngine(Collections.emptyList(),
Collections.singleton(SelectStatement.class)).isSupported(mock(SelectStatement.class)));
+ }
+
+ @Test
+ void assertIsSupportedWithOverlappedList() {
+ assertTrue(new
SupportedSQLStatementJudgeEngine(Collections.singleton(SelectStatement.class),
Collections.singleton(SQLStatement.class)).isSupported(mock(SelectStatement.class)));
+ }
+
+ @Test
+ void assertIsSupportedWithoutList() {
+ assertTrue(new
SupportedSQLStatementJudgeEngine(Collections.singleton(SelectStatement.class),
Collections.singleton(UpdateStatement.class)).isSupported(mock(DeleteStatement.class)));
+ }
+}
diff --git
a/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/MySQLSetCharsetExecutor.java
b/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/MySQLSetCharsetExecutor.java
index 996ced9a680..9583ddec930 100644
---
a/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/MySQLSetCharsetExecutor.java
+++
b/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/MySQLSetCharsetExecutor.java
@@ -22,6 +22,7 @@ import
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLConstants;
import
org.apache.shardingsphere.dialect.mysql.exception.UnknownCharsetException;
import
org.apache.shardingsphere.proxy.backend.mysql.handler.admin.MySQLSessionVariableHandler;
import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@@ -48,7 +49,7 @@ public final class MySQLSetCharsetExecutor implements
MySQLSessionVariableHandle
}
private String formatValue(final String value) {
- return value.startsWith("'") && value.endsWith("'") ||
value.startsWith("\"") && value.endsWith("\"") ? value.substring(1,
value.length() - 1) : value.trim();
+ return QuoteCharacter.SINGLE_QUOTE.isWrapped(value) ||
QuoteCharacter.QUOTE.isWrapped(value) ? value.substring(1, value.length() - 1)
: value.trim();
}
private Charset parseCharset(final String value) {
diff --git
a/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLCharacterSets.java
b/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLCharacterSets.java
index ba4d756dbac..96b22befc3a 100644
---
a/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLCharacterSets.java
+++
b/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLCharacterSets.java
@@ -17,6 +17,8 @@
package org.apache.shardingsphere.proxy.backend.postgresql.handler.admin;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
+
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
@@ -113,6 +115,6 @@ public enum PostgreSQLCharacterSets {
}
private static String formatValue(final String value) {
- return value.startsWith("'") && value.endsWith("'") ||
value.startsWith("\"") && value.endsWith("\"") ? value.substring(1,
value.length() - 1) : value.trim();
+ return QuoteCharacter.SINGLE_QUOTE.isWrapped(value) ||
QuoteCharacter.QUOTE.isWrapped(value) ? value.substring(1, value.length() - 1)
: value.trim();
}
}
diff --git
a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java
b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java
index a19d5a770ed..293dbc77892 100644
---
a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java
+++
b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java
@@ -82,9 +82,16 @@ public final class MySQLComQueryPacketExecutor implements
QueryCommandExecutor {
private boolean areMultiStatements(final ConnectionSession
connectionSession, final SQLStatement sqlStatement, final String sql) {
// TODO Multi statements should be identified by SQL Parser instead of
checking if sql contains ";".
+ return isMultiStatementsEnabled(connectionSession) &&
isSuitableMultiStatementsSQLStatement(sqlStatement) && sql.contains(";");
+ }
+
+ private boolean isMultiStatementsEnabled(final ConnectionSession
connectionSession) {
return
connectionSession.getAttributeMap().hasAttr(MySQLConstants.MYSQL_OPTION_MULTI_STATEMENTS)
- && MySQLComSetOptionPacket.MYSQL_OPTION_MULTI_STATEMENTS_ON ==
connectionSession.getAttributeMap().attr(MySQLConstants.MYSQL_OPTION_MULTI_STATEMENTS).get()
- && (sqlStatement instanceof UpdateStatement || sqlStatement
instanceof DeleteStatement) && sql.contains(";");
+ && MySQLComSetOptionPacket.MYSQL_OPTION_MULTI_STATEMENTS_ON ==
connectionSession.getAttributeMap().attr(MySQLConstants.MYSQL_OPTION_MULTI_STATEMENTS).get();
+ }
+
+ private boolean isSuitableMultiStatementsSQLStatement(final SQLStatement
sqlStatement) {
+ return sqlStatement instanceof UpdateStatement || sqlStatement
instanceof DeleteStatement;
}
@Override
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/DefaultExternalTestParameterLoader.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/DefaultExternalTestParameterLoader.java
index 92aba08961f..d3ebcfb53b3 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/DefaultExternalTestParameterLoader.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/DefaultExternalTestParameterLoader.java
@@ -69,11 +69,7 @@ public final class DefaultExternalTestParameterLoader
extends AbstractTestParame
}
private String getStatement(final String completedSQL, final String
rawSQLLine, final boolean inProcedure) {
- return (rawSQLLine.isEmpty() || isComment(rawSQLLine)) && !inProcedure
? "" : completedSQL + rawSQLLine + " ";
- }
-
- private boolean isComment(final String line) {
- return line.startsWith("#") || line.startsWith("/") ||
line.startsWith("--") || line.startsWith(":") || line.startsWith("\\");
+ return (rawSQLLine.isEmpty() || SQLLineComment.isComment(rawSQLLine))
&& !inProcedure ? "" : completedSQL + rawSQLLine + " ";
}
private int searchInResultContent(final int resultIndex, final
List<String> resultLines, final String completedSQL, final int statementLines) {
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/ExternalMySQLTestParameterLoader.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/ExternalMySQLTestParameterLoader.java
index afd52d15320..22f46f1a214 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/ExternalMySQLTestParameterLoader.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/ExternalMySQLTestParameterLoader.java
@@ -47,7 +47,7 @@ public final class ExternalMySQLTestParameterLoader extends
AbstractTestParamete
String delimiter = ";";
for (String each : sqlCaseFileContent) {
String line = each.trim();
- if (line.isEmpty() || lines.isEmpty() && isComment(line)) {
+ if (line.isEmpty() || lines.isEmpty() &&
SQLLineComment.isComment(line)) {
continue;
}
if (lines.isEmpty() && line.toUpperCase().startsWith("DELIMITER"))
{
@@ -68,10 +68,6 @@ public final class ExternalMySQLTestParameterLoader extends
AbstractTestParamete
return result;
}
- private boolean isComment(final String line) {
- return line.startsWith("#") || line.startsWith("/") ||
line.startsWith("--") || line.startsWith(":") || line.startsWith("\\");
- }
-
private String getNewDelimiter(final String sql, final String delimiter) {
String newDelimiter = sql.substring(DELIMITER_COMMAND_LENGTH,
sql.endsWith(delimiter) ? sql.length() - delimiter.length() :
sql.length()).trim();
if (newDelimiter.startsWith("\"") && newDelimiter.endsWith("\"") ||
newDelimiter.startsWith("'") && newDelimiter.endsWith("'")) {
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/spi/ProxyClusterState.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/SQLLineComment.java
similarity index 56%
rename from
proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/spi/ProxyClusterState.java
rename to
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/SQLLineComment.java
index 175c9bb71de..7c919cd9b4a 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/state/spi/ProxyClusterState.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/SQLLineComment.java
@@ -15,20 +15,30 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.state.spi;
+package org.apache.shardingsphere.test.it.sql.parser.external.loader;
-import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPI;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.Arrays;
+import java.util.Collection;
/**
- * Proxy cluster state.
+ * SQL line comment.
*/
-public interface ProxyClusterState extends TypedSPI {
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class SQLLineComment {
+
+ private static final Collection<String> COMMENT_PREFIXES =
Arrays.asList("#", "/", "--", ":", "\\");
/**
- * Check sql statement.
+ * Judge whether SQL line is comment.
*
- * @param sqlStatement sql statement
+ * @param line SQL line
+ * @return SQL line is comment or not
*/
- void check(SQLStatement sqlStatement);
+ public static boolean isComment(final String line) {
+ return COMMENT_PREFIXES.stream().anyMatch(line::startsWith);
+ }
+
}