This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 7e63199751c Fix nullable metadata consumers and JDBC statement
initialization (#40300)
7e63199751c is described below
commit 7e63199751c4c5143f4fd82fbd10ea04bf77bb1a
Author: Liang Zhang <[email protected]>
AuthorDate: Wed Oct 21 01:01:57 2026 +0800
Fix nullable metadata consumers and JDBC statement initialization (#40300)
* Fix nullable metadata consumers and JDBC statement initialization
* Fix nullable metadata consumer test fixtures
* Fix Firebird describe schema consistency during metadata refresh
---
.../PostgreSQLPgClassTableStatisticsCollector.java | 6 +-
...tgreSQLPgNamespaceTableStatisticsCollector.java | 6 +-
...tgreSQLPgClassTableStatisticsCollectorTest.java | 8 +
...SQLPgNamespaceTableStatisticsCollectorTest.java | 15 ++
.../export/ExportStorageNodesExecutor.java | 16 +-
.../metadata/RefreshTableMetaDataExecutor.java | 24 ++-
.../statement/ShardingSpherePreparedStatement.java | 4 +
.../core/statement/ShardingSphereStatement.java | 5 +
.../ShardingSpherePreparedStatementTest.java | 56 ++++++
.../statement/ShardingSphereStatementTest.java | 91 ++++++++++
.../statistics/StatisticsRefreshEngine.java | 11 +-
.../statistics/StatisticsRefreshEngineTest.java | 115 ++++++++++++
.../connector/jdbc/executor/ProxyJDBCExecutor.java | 4 +-
.../jdbc/executor/ProxyJDBCExecutorTest.java | 58 +++++-
.../DistSQLUpdateProxyBackendHandlerTest.java | 4 +-
.../export/ExportStorageNodesExecutorTest.java | 13 +-
.../refresh/RefreshTableMetaDataExecutorTest.java | 17 +-
.../FirebirdPrepareStatementCommandExecutor.java | 72 ++++----
...irebirdPrepareStatementCommandExecutorTest.java | 202 +++++++++++++++++++++
19 files changed, 658 insertions(+), 69 deletions(-)
diff --git
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollector.java
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollector.java
index 3d090e5a27f..1ac968a4af3 100644
---
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollector.java
+++
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollector.java
@@ -18,7 +18,9 @@
package
org.apache.shardingsphere.infra.metadata.statistics.collector.postgresql.table;
import com.cedarsoftware.util.CaseInsensitiveMap;
+import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
import
org.apache.shardingsphere.infra.metadata.statistics.collector.postgresql.PostgreSQLTableStatisticsCollector;
@@ -36,8 +38,10 @@ public final class PostgreSQLPgClassTableStatisticsCollector
implements PostgreS
@Override
public Collection<Map<String, Object>> collect(final String databaseName,
final String schemaName, final String tableName, final ShardingSphereMetaData
metaData) {
+ ShardingSphereDatabase database = metaData.getDatabase(databaseName);
+ ShardingSpherePreconditions.checkNotNull(database, () -> new
IllegalStateException(String.format("Database '%s' does not exist.",
databaseName)));
Collection<Map<String, Object>> result = new LinkedList<>();
- ShardingSphereSchema publicSchema =
metaData.getDatabase(databaseName).getSchema(PUBLIC_SCHEMA);
+ ShardingSphereSchema publicSchema = database.getSchema(PUBLIC_SCHEMA);
if (null != publicSchema) {
for (ShardingSphereTable each : publicSchema.getAllTables()) {
Map<String, Object> columnValues = new CaseInsensitiveMap<>(4,
1F);
diff --git
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollector.java
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollector.java
index 5820f70eeda..3e9f95d19e3 100644
---
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollector.java
+++
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollector.java
@@ -18,7 +18,9 @@
package
org.apache.shardingsphere.infra.metadata.statistics.collector.postgresql.table;
import com.cedarsoftware.util.CaseInsensitiveMap;
+import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
import
org.apache.shardingsphere.infra.metadata.statistics.collector.postgresql.PostgreSQLTableStatisticsCollector;
@@ -37,9 +39,11 @@ public final class
PostgreSQLPgNamespaceTableStatisticsCollector implements Post
@Override
public Collection<Map<String, Object>> collect(final String databaseName,
final String schemaName, final String tableName, final ShardingSphereMetaData
metaData) {
+ ShardingSphereDatabase database = metaData.getDatabase(databaseName);
+ ShardingSpherePreconditions.checkNotNull(database, () -> new
IllegalStateException(String.format("Database '%s' does not exist.",
databaseName)));
Collection<Map<String, Object>> result = new LinkedList<>();
long oid = 1L;
- for (ShardingSphereSchema each :
metaData.getDatabase(databaseName).getAllSchemas()) {
+ for (ShardingSphereSchema each : database.getAllSchemas()) {
Map<String, Object> columnValues = new CaseInsensitiveMap<>(2, 1F);
columnValues.put("oid",
PUBLIC_SCHEMA.equalsIgnoreCase(each.getName()) ? PUBLIC_SCHEMA_OID : oid++);
columnValues.put("nspname", each.getName());
diff --git
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollectorTest.java
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollectorTest.java
index 5f32bb819c2..047a9d07afc 100644
---
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollectorTest.java
+++
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgClassTableStatisticsCollectorTest.java
@@ -33,6 +33,7 @@ import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -66,6 +67,13 @@ class PostgreSQLPgClassTableStatisticsCollectorTest {
assertTrue(actual.isEmpty());
}
+ @Test
+ void assertCollectWithDatabaseNotExists() {
+ when(metaData.getDatabase("foo_db")).thenReturn(null);
+ IllegalStateException actual =
assertThrows(IllegalStateException.class, () -> collector.collect("foo_db",
"pg_catalog", "pg_class", metaData));
+ assertThat(actual.getMessage(), is("Database 'foo_db' does not
exist."));
+ }
+
@Test
void assertGetSchemaName() {
assertThat(collector.getSchemaName(), is("pg_catalog"));
diff --git
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollectorTest.java
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollectorTest.java
index 392e241db2a..0ee993754df 100644
---
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollectorTest.java
+++
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/statistics/collector/postgresql/table/PostgreSQLPgNamespaceTableStatisticsCollectorTest.java
@@ -37,6 +37,8 @@ import java.util.stream.Collectors;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
class PostgreSQLPgNamespaceTableStatisticsCollectorTest {
@@ -62,6 +64,19 @@ class PostgreSQLPgNamespaceTableStatisticsCollectorTest {
assertThat(actualResults.get("bar_schema").get("nspname"),
is("bar_schema"));
}
+ @Test
+ void assertCollectWithNoSchemas() {
+ assertTrue(collector.collect("foo_db", "pg_catalog", "pg_namespace",
createMetaData(Collections.emptyList())).isEmpty());
+ }
+
+ @Test
+ void assertCollectWithDatabaseNotExists() {
+ ShardingSphereMetaData metaData =
createMetaData(Collections.emptyList());
+ metaData.dropDatabase("foo_db");
+ IllegalStateException actual =
assertThrows(IllegalStateException.class, () -> collector.collect("foo_db",
"pg_catalog", "pg_namespace", metaData));
+ assertThat(actual.getMessage(), is("Database 'foo_db' does not
exist."));
+ }
+
@Test
void assertGetSchemaName() {
assertThat(collector.getSchemaName(), is("pg_catalog"));
diff --git
a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/ExportStorageNodesExecutor.java
b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/ExportStorageNodesExecutor.java
index 3a89039c37c..347856361c9 100644
---
a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/ExportStorageNodesExecutor.java
+++
b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/ExportStorageNodesExecutor.java
@@ -52,7 +52,6 @@ public final class ExportStorageNodesExecutor implements
DistSQLQueryExecutor<Ex
@Override
public Collection<LocalDataQueryResultRow> getRows(final
ExportStorageNodesStatement sqlStatement, final ContextManager contextManager) {
- checkSQLStatement(contextManager.getMetaDataContexts().getMetaData(),
sqlStatement);
String exportedData =
generateExportData(contextManager.getMetaDataContexts().getMetaData(),
sqlStatement);
if (sqlStatement.getFilePath().isPresent()) {
String filePath = sqlStatement.getFilePath().get();
@@ -64,16 +63,15 @@ public final class ExportStorageNodesExecutor implements
DistSQLQueryExecutor<Ex
new
LocalDataQueryResultRow(contextManager.getComputeNodeInstanceContext().getInstance().getMetaData().getId(),
LocalDateTime.now(), exportedData));
}
- private void checkSQLStatement(final ShardingSphereMetaData metaData,
final ExportStorageNodesStatement sqlStatement) {
- ShardingSpherePreconditions.checkState(null ==
sqlStatement.getDatabaseName() || null !=
metaData.getDatabase(sqlStatement.getDatabaseName()),
- () -> new IllegalArgumentException(String.format("database %s
is not existed", sqlStatement.getDatabaseName())));
- }
-
private String generateExportData(final ShardingSphereMetaData metaData,
final ExportStorageNodesStatement sqlStatement) {
ExportedStorageNodes storageNodes = new ExportedStorageNodes();
- storageNodes.setStorageNodes(null == sqlStatement.getDatabaseName()
- ? getAllStorageNodes(metaData)
- :
generateDatabaseExportStorageNodesData(metaData.getDatabase(sqlStatement.getDatabaseName())));
+ if (null == sqlStatement.getDatabaseName()) {
+ storageNodes.setStorageNodes(getAllStorageNodes(metaData));
+ } else {
+ ShardingSphereDatabase database =
metaData.getDatabase(sqlStatement.getDatabaseName());
+ ShardingSpherePreconditions.checkNotNull(database, () -> new
IllegalArgumentException(String.format("database %s is not existed",
sqlStatement.getDatabaseName())));
+
storageNodes.setStorageNodes(generateDatabaseExportStorageNodesData(database));
+ }
return JsonEngine.marshal(storageNodes);
}
diff --git
a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/metadata/RefreshTableMetaDataExecutor.java
b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/metadata/RefreshTableMetaDataExecutor.java
index 56bd68af816..8c7826f1a7f 100644
---
a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/metadata/RefreshTableMetaDataExecutor.java
+++
b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/metadata/RefreshTableMetaDataExecutor.java
@@ -28,6 +28,7 @@ import
org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storag
import
org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
+import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
import org.apache.shardingsphere.mode.manager.ContextManager;
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
@@ -45,9 +46,9 @@ public final class RefreshTableMetaDataExecutor implements
DistSQLUpdateExecutor
@Override
public void executeUpdate(final RefreshTableMetaDataStatement
sqlStatement, final ContextManager contextManager) {
IdentifierValue schemaName = getSchemaName(sqlStatement);
- checkBeforeUpdate(sqlStatement, schemaName);
+ ShardingSphereSchema schema = checkBeforeUpdate(sqlStatement,
schemaName);
if (sqlStatement.getStorageUnitName().isPresent()) {
- String actualSchemaName = database.getSchema(schemaName).getName();
+ String actualSchemaName = schema.getName();
if (sqlStatement.getTableName().isPresent()) {
contextManager.reloadTable(database, actualSchemaName,
sqlStatement.getStorageUnitName().get(), sqlStatement.getTableName().get());
} else {
@@ -56,7 +57,7 @@ public final class RefreshTableMetaDataExecutor implements
DistSQLUpdateExecutor
return;
}
if (sqlStatement.getTableName().isPresent()) {
- contextManager.reloadTable(database,
database.getSchema(schemaName).getName(), sqlStatement.getTableName().get());
+ contextManager.reloadTable(database, schema.getName(),
sqlStatement.getTableName().get());
} else {
contextManager.reloadDatabase(database);
}
@@ -66,10 +67,11 @@ public final class RefreshTableMetaDataExecutor implements
DistSQLUpdateExecutor
return sqlStatement.getSchemaName().orElseGet(() -> new
IdentifierValue(database.getDefaultSchemaName()));
}
- private void checkBeforeUpdate(final RefreshTableMetaDataStatement
sqlStatement, final IdentifierValue schemaName) {
+ private ShardingSphereSchema checkBeforeUpdate(final
RefreshTableMetaDataStatement sqlStatement, final IdentifierValue schemaName) {
checkStorageUnit(database.getResourceMetaData().getStorageUnits(),
sqlStatement);
- checkSchema(schemaName);
- checkTable(sqlStatement, schemaName);
+ ShardingSphereSchema result = checkSchema(schemaName);
+ checkTable(sqlStatement, result);
+ return result;
}
private void checkStorageUnit(final Map<String, StorageUnit> storageUnits,
final RefreshTableMetaDataStatement sqlStatement) {
@@ -80,14 +82,16 @@ public final class RefreshTableMetaDataExecutor implements
DistSQLUpdateExecutor
}
}
- private void checkSchema(final IdentifierValue schemaName) {
-
ShardingSpherePreconditions.checkState(database.containsSchema(schemaName), ()
-> new SchemaNotFoundException(schemaName.getValue()));
+ private ShardingSphereSchema checkSchema(final IdentifierValue schemaName)
{
+ ShardingSphereSchema result = database.getSchema(schemaName);
+ ShardingSpherePreconditions.checkNotNull(result, () -> new
SchemaNotFoundException(schemaName.getValue()));
+ return result;
}
- private void checkTable(final RefreshTableMetaDataStatement sqlStatement,
final IdentifierValue schemaName) {
+ private void checkTable(final RefreshTableMetaDataStatement sqlStatement,
final ShardingSphereSchema schema) {
if (sqlStatement.getTableName().isPresent()) {
IdentifierValue tableName = sqlStatement.getTableName().get();
-
ShardingSpherePreconditions.checkState(database.getSchema(schemaName).containsTable(tableName),
() -> new TableNotFoundException(tableName.getValue()));
+
ShardingSpherePreconditions.checkState(schema.containsTable(tableName), () ->
new TableNotFoundException(tableName.getValue()));
}
}
diff --git
a/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
b/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
index 3ba1dd62bda..52c2d7ee184 100644
---
a/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
+++
b/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
@@ -22,6 +22,7 @@ import lombok.Getter;
import
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.keygen.DialectGeneratedKeyOption;
import
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
import
org.apache.shardingsphere.database.exception.core.SQLExceptionTransformEngine;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.distsql.statement.DistSQLStatement;
import
org.apache.shardingsphere.driver.executor.callback.add.StatementAddCallback;
import
org.apache.shardingsphere.driver.executor.callback.replay.StatementReplayCallback;
@@ -148,6 +149,8 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
sql = SQLHintUtils.removeHint(originSQL);
hintValueContext = SQLHintUtils.extractHint(originSQL);
ShardingSphereDatabase currentDatabase =
metaData.getDatabase(connection.getCurrentDatabaseName());
+ ShardingSpherePreconditions.checkNotNull(currentDatabase,
+ () -> SQLExceptionTransformEngine.toSQLException(new
UnknownDatabaseException(connection.getCurrentDatabaseName()),
metaData.getProtocolType()));
SQLStatement sqlStatement =
metaData.getGlobalRuleMetaData().getSingleRule(SQLParserRule.class).getSQLParserEngine(currentDatabase.getProtocolType()).parse(sql,
true);
sqlStatementContext = sqlStatement instanceof DistSQLStatement
? new CommonSQLStatementContext(sqlStatement)
@@ -155,6 +158,7 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
String usedDatabaseName =
sqlStatementContext.getTablesContext().getDatabaseName().orElse(connection.getCurrentDatabaseName());
connection.getDatabaseConnectionManager().getConnectionContext().setCurrentDatabaseName(connection.getCurrentDatabaseName());
usedDatabase = metaData.getDatabase(usedDatabaseName);
+ ShardingSpherePreconditions.checkNotNull(usedDatabase, () ->
SQLExceptionTransformEngine.toSQLException(new
UnknownDatabaseException(usedDatabaseName), currentDatabase.getProtocolType()));
statementOption = returnGeneratedKeys ? new StatementOption(true,
columns) : new StatementOption(resultSetType, resultSetConcurrency,
resultSetHoldability);
statementManager = new StatementManager();
connection.registerStatementManager(statementManager);
diff --git
a/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
b/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
index c90c8cb7c0a..635a3273b26 100644
---
a/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
+++
b/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegist
import
org.apache.shardingsphere.database.exception.core.SQLExceptionTransformEngine;
import
org.apache.shardingsphere.database.exception.core.exception.SQLDialectException;
import
org.apache.shardingsphere.database.exception.core.exception.protocol.DatabaseProtocolException;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.distsql.statement.DistSQLStatement;
import
org.apache.shardingsphere.driver.executor.callback.add.StatementAddCallback;
import
org.apache.shardingsphere.driver.executor.callback.execute.StatementExecuteCallback;
@@ -300,6 +301,7 @@ public final class ShardingSphereStatement extends
AbstractStatementAdapter {
HintValueContext hintValueContext =
SQLHintUtils.extractHint(originSQL);
String sql = SQLHintUtils.removeHint(originSQL);
ShardingSphereDatabase currentDatabase =
metaData.getDatabase(usedDatabaseName);
+ ShardingSpherePreconditions.checkNotNull(currentDatabase, () ->
SQLExceptionTransformEngine.toSQLException(new
UnknownDatabaseException(usedDatabaseName), metaData.getProtocolType()));
DatabaseType databaseType = currentDatabase.getProtocolType();
SQLStatement sqlStatement =
metaData.getGlobalRuleMetaData().getSingleRule(SQLParserRule.class).getSQLParserEngine(databaseType).parse(sql,
false);
SQLStatementContext sqlStatementContext = sqlStatement instanceof
DistSQLStatement
@@ -422,6 +424,9 @@ public final class ShardingSphereStatement extends
AbstractStatementAdapter {
}
private Optional<GeneratedKeyContext> findGeneratedKey() {
+ if (null == queryContext) {
+ return Optional.empty();
+ }
SQLStatementContext sqlStatementContext =
queryContext.getSqlStatementContext();
return sqlStatementContext instanceof InsertStatementContext ?
((InsertStatementContext) sqlStatementContext).getGeneratedKeyContext() :
Optional.empty();
}
diff --git
a/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
b/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
index 91d667207ae..2523751697b 100644
---
a/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
+++
b/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
@@ -21,7 +21,9 @@ import lombok.SneakyThrows;
import
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
+import
org.apache.shardingsphere.database.exception.core.SQLExceptionTransformEngine;
import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
+import org.apache.shardingsphere.distsql.statement.type.rul.sql.ParseStatement;
import
org.apache.shardingsphere.driver.executor.engine.facade.DriverExecutorFacade;
import
org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
import
org.apache.shardingsphere.driver.jdbc.core.resultset.GeneratedKeysResultSet;
@@ -45,6 +47,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
import org.mockito.internal.configuration.plugins.Plugins;
import java.lang.reflect.Field;
@@ -70,15 +73,68 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class ShardingSpherePreparedStatementTest {
+ @Test
+ void assertCreatePreparedStatementAfterDatabaseRemoved() {
+ DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+ ShardingSphereMetaData metaData = createMetaData(databaseType);
+ ShardingSphereConnection connection =
mock(ShardingSphereConnection.class, RETURNS_DEEP_STUBS);
+
when(connection.getContextManager().getMetaDataContexts().getMetaData()).thenReturn(metaData);
+ when(connection.getCurrentDatabaseName()).thenReturn("foo_db");
+ when(metaData.getProtocolType()).thenReturn(databaseType);
+ when(metaData.getDatabase("foo_db")).thenReturn(null);
+ SQLException expected = new SQLException("Unknown database 'foo_db'",
"42000", 1049);
+ try (MockedStatic<SQLExceptionTransformEngine> mockedEngine =
mockStatic(SQLExceptionTransformEngine.class, CALLS_REAL_METHODS)) {
+ mockedEngine.when(() -> SQLExceptionTransformEngine.toSQLException(
+ argThat(ex -> ex instanceof UnknownDatabaseException &&
"foo_db".equals(((UnknownDatabaseException) ex).getDatabaseName())),
same(databaseType))).thenReturn(expected);
+ SQLException actual = assertThrows(SQLException.class, () -> new
ShardingSpherePreparedStatement(connection, "SELECT 1"));
+ assertThat(actual, sameInstance(expected));
+ assertThat(actual.getMessage(), is("Unknown database 'foo_db'"));
+ assertThat(actual.getSQLState(), is("42000"));
+ assertThat(actual.getErrorCode(), is(1049));
+ }
+ verify(connection, never()).registerStatementManager(any());
+ }
+
+ @Test
+ void assertCreatePreparedStatementWhenDatabaseRemovedDuringParsing() {
+ DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+ ShardingSphereMetaData metaData = createMetaData(databaseType);
+ ShardingSphereConnection connection =
mock(ShardingSphereConnection.class, RETURNS_DEEP_STUBS);
+
when(connection.getContextManager().getMetaDataContexts().getMetaData()).thenReturn(metaData);
+ when(connection.getCurrentDatabaseName()).thenReturn("foo_db");
+
when(metaData.getProtocolType()).thenReturn(TypedSPILoader.getService(DatabaseType.class,
"PostgreSQL"));
+ SQLParserRule parserRule = mock(SQLParserRule.class,
RETURNS_DEEP_STUBS);
+ when(metaData.getGlobalRuleMetaData()).thenReturn(new
RuleMetaData(Collections.singletonList(parserRule)));
+ when(parserRule.getSQLParserEngine(databaseType).parse("foo_distsql",
true)).thenAnswer(invocation -> {
+ when(metaData.getDatabase("foo_db")).thenReturn(null);
+ return new ParseStatement("SELECT 1");
+ });
+ SQLException expected = new SQLException("Unknown database 'foo_db'",
"42000", 1049);
+ try (MockedStatic<SQLExceptionTransformEngine> mockedEngine =
mockStatic(SQLExceptionTransformEngine.class, CALLS_REAL_METHODS)) {
+ mockedEngine.when(() -> SQLExceptionTransformEngine.toSQLException(
+ argThat(ex -> ex instanceof UnknownDatabaseException &&
"foo_db".equals(((UnknownDatabaseException) ex).getDatabaseName())),
same(databaseType))).thenReturn(expected);
+ SQLException actual = assertThrows(SQLException.class, () -> new
ShardingSpherePreparedStatement(connection, "foo_distsql"));
+ assertThat(actual, sameInstance(expected));
+ assertThat(actual.getMessage(), is("Unknown database 'foo_db'"));
+ assertThat(actual.getSQLState(), is("42000"));
+ assertThat(actual.getErrorCode(), is(1049));
+ }
+ verify(connection, never()).registerStatementManager(any());
+ }
+
@SuppressWarnings("unchecked")
@Test
void assertClearBatchResetsCachedGeneratedKeysResultSet() throws
SQLException, ReflectiveOperationException {
diff --git
a/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatementTest.java
b/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatementTest.java
index f86742f03a3..d22642d117b 100644
---
a/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatementTest.java
+++
b/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatementTest.java
@@ -59,12 +59,16 @@ import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
@@ -76,6 +80,26 @@ import static org.mockito.Mockito.when;
class ShardingSphereStatementTest {
+ @Test
+ void assertGetGeneratedKeysBeforeExecutionWithoutDialectColumn() throws
SQLException {
+ ShardingSphereStatement statement =
createStatement(TypedSPILoader.getService(DatabaseType.class, "SQL92"));
+ try (ResultSet actual = statement.getGeneratedKeys()) {
+ assertFalse(actual.next());
+ assertNull(actual.getMetaData().getColumnName(1));
+ assertThat(actual.getStatement(), sameInstance(statement));
+ }
+ }
+
+ @Test
+ void assertGetGeneratedKeysBeforeExecutionWithDialectColumn() throws
SQLException {
+ ShardingSphereStatement statement =
createStatement(TypedSPILoader.getService(DatabaseType.class, "MySQL"));
+ try (ResultSet actual = statement.getGeneratedKeys()) {
+ assertFalse(actual.next());
+ assertThat(actual.getMetaData().getColumnName(1),
is("GENERATED_KEY"));
+ assertThat(actual.getStatement(), sameInstance(statement));
+ }
+ }
+
@Test
void assertGetGeneratedKeysByColumnIndexWhenColumnNameMissing() throws
SQLException {
ResultSet generatedKeys = mock(ResultSet.class);
@@ -133,6 +157,73 @@ class ShardingSphereStatementTest {
assertThat(assertThrows(UnknownDatabaseException.class,
statement::getGeneratedKeys), sameInstance(expected));
}
+ @Test
+ void assertGetGeneratedKeysBeforeExecutionAfterDatabaseRemoved() {
+ ShardingSphereStatement statement =
createStatement(TypedSPILoader.getService(DatabaseType.class, "MySQL"));
+ UnknownDatabaseException expected =
removeDatabase(statement.getConnection());
+ assertThat(assertThrows(UnknownDatabaseException.class,
statement::getGeneratedKeys), sameInstance(expected));
+ }
+
+ @Test
+ void assertExecuteQueryAfterDatabaseRemoved() {
+ DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+ ShardingSphereStatement statement = createStatement(databaseType);
+ removeDatabase(statement.getConnection());
+ SQLException expected = new SQLException("Unknown database 'foo_db'",
"42000", 1049);
+ try (MockedStatic<SQLExceptionTransformEngine> mockedEngine =
mockStatic(SQLExceptionTransformEngine.class, CALLS_REAL_METHODS)) {
+ mockedEngine.when(() -> SQLExceptionTransformEngine.toSQLException(
+ argThat(ex -> ex instanceof UnknownDatabaseException &&
"foo_db".equals(((UnknownDatabaseException) ex).getDatabaseName())),
same(databaseType))).thenReturn(expected);
+ SQLException actual = assertThrows(SQLException.class, () ->
statement.executeQuery("SELECT 1"));
+ assertThat(actual, sameInstance(expected));
+ assertThat(actual.getMessage(), is("Unknown database 'foo_db'"));
+ assertThat(actual.getSQLState(), is("42000"));
+ assertThat(actual.getErrorCode(), is(1049));
+ }
+ }
+
+ @Test
+ void assertExecuteQueryAfterDatabaseRemovedWithoutDialectMapper() {
+ ShardingSphereStatement statement =
createStatement(TypedSPILoader.getService(DatabaseType.class, "SQL92"));
+ removeDatabase(statement.getConnection());
+ SQLException actual = assertThrows(SQLException.class, () ->
statement.executeQuery("SELECT 1"));
+ assertThat(actual.getCause(), isA(UnknownDatabaseException.class));
+ assertThat(((UnknownDatabaseException)
actual.getCause()).getDatabaseName(), is("foo_db"));
+ }
+
+ @Test
+ void assertExecuteUpdateAfterDatabaseRemoved() {
+ DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+ ShardingSphereStatement statement = createStatement(databaseType);
+ removeDatabase(statement.getConnection());
+ SQLException expected = new SQLException("Unknown database 'foo_db'",
"42000", 1049);
+ try (MockedStatic<SQLExceptionTransformEngine> mockedEngine =
mockStatic(SQLExceptionTransformEngine.class, CALLS_REAL_METHODS)) {
+ mockedEngine.when(() -> SQLExceptionTransformEngine.toSQLException(
+ argThat(ex -> ex instanceof UnknownDatabaseException &&
"foo_db".equals(((UnknownDatabaseException) ex).getDatabaseName())),
same(databaseType))).thenReturn(expected);
+ SQLException actual = assertThrows(SQLException.class, () ->
statement.executeUpdate("UPDATE foo_table SET id = 1"));
+ assertThat(actual, sameInstance(expected));
+ assertThat(actual.getMessage(), is("Unknown database 'foo_db'"));
+ assertThat(actual.getSQLState(), is("42000"));
+ assertThat(actual.getErrorCode(), is(1049));
+ }
+ }
+
+ @Test
+ void assertExecuteAfterDatabaseRemoved() {
+ DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+ ShardingSphereStatement statement = createStatement(databaseType);
+ removeDatabase(statement.getConnection());
+ SQLException expected = new SQLException("Unknown database 'foo_db'",
"42000", 1049);
+ try (MockedStatic<SQLExceptionTransformEngine> mockedEngine =
mockStatic(SQLExceptionTransformEngine.class, CALLS_REAL_METHODS)) {
+ mockedEngine.when(() -> SQLExceptionTransformEngine.toSQLException(
+ argThat(ex -> ex instanceof UnknownDatabaseException &&
"foo_db".equals(((UnknownDatabaseException) ex).getDatabaseName())),
same(databaseType))).thenReturn(expected);
+ SQLException actual = assertThrows(SQLException.class, () ->
statement.execute("SELECT 1"));
+ assertThat(actual, sameInstance(expected));
+ assertThat(actual.getMessage(), is("Unknown database 'foo_db'"));
+ assertThat(actual.getSQLState(), is("42000"));
+ assertThat(actual.getErrorCode(), is(1049));
+ }
+ }
+
@Test
void assertGetGeneratedKeysWithoutColumnName() throws SQLException,
ReflectiveOperationException {
ShardingSphereStatement statement =
createStatement(TypedSPILoader.getService(DatabaseType.class, "SQL92"));
diff --git
a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngine.java
b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngine.java
index 0adf384e5ce..80549bc8160 100644
---
a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngine.java
+++
b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngine.java
@@ -85,21 +85,22 @@ public final class StatisticsRefreshEngine {
private void refreshForDatabase(final ShardingSphereMetaData metaData,
final ShardingSphereDatabase database) {
for (ShardingSphereSchema each : database.getAllSchemas()) {
- refreshForSchema(metaData, database.getName(), each);
+ refreshForSchema(metaData, database, each);
}
}
- private void refreshForSchema(final ShardingSphereMetaData metaData, final
String databaseName, final ShardingSphereSchema schema) {
+ private void refreshForSchema(final ShardingSphereMetaData metaData, final
ShardingSphereDatabase database, final ShardingSphereSchema schema) {
for (ShardingSphereTable each : schema.getAllTables()) {
- refreshForTable(metaData, databaseName, schema.getName(), each);
+ refreshForTable(metaData, database, schema.getName(), each);
}
}
- private void refreshForTable(final ShardingSphereMetaData metaData, final
String databaseName, final String schemaName, final ShardingSphereTable table) {
+ private void refreshForTable(final ShardingSphereMetaData metaData, final
ShardingSphereDatabase database, final String schemaName, final
ShardingSphereTable table) {
+ String databaseName = database.getName();
try {
Optional<DialectDatabaseStatisticsCollector>
dialectStatisticsCollector = "shardingsphere".equalsIgnoreCase(schemaName)
? Optional.of(new ShardingSphereStatisticsCollector())
- :
DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class,
metaData.getDatabase(databaseName).getProtocolType());
+ :
DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class,
database.getProtocolType());
if (dialectStatisticsCollector.isPresent()) {
Optional<Collection<Map<String, Object>>> rowColumnValues =
dialectStatisticsCollector.get().collectRowColumnValues(databaseName,
schemaName, table.getName(), metaData);
rowColumnValues.ifPresent(optional -> new
StatisticsStorageEngine(contextManager, databaseName, schemaName,
table.getName(), optional).storage());
diff --git
a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngineTest.java
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngineTest.java
new file mode 100644
index 00000000000..7917cc7ae7b
--- /dev/null
+++
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/statistics/StatisticsRefreshEngineTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.mode.manager.cluster.statistics;
+
+import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationProperties;
+import
org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationPropertyKey;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import
org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector;
+import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
+import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
+import org.apache.shardingsphere.mode.exclusive.ExclusiveOperatorEngine;
+import
org.apache.shardingsphere.mode.exclusive.callback.ExclusiveOperationVoidCallback;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Properties;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(DatabaseTypedSPILoader.class)
+class StatisticsRefreshEngineTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ContextManager contextManager;
+
+ @Mock
+ private ShardingSphereMetaData metaData;
+
+ @Mock
+ private ShardingSphereDatabase database;
+
+ @Mock
+ private ShardingSphereSchema schema;
+
+ @Mock
+ private DatabaseType databaseType;
+
+ @Mock
+ private DialectDatabaseStatisticsCollector collector;
+
+ @BeforeEach
+ void setUp() throws SQLException {
+ Properties props = PropertiesBuilder.build(new
Property(TemporaryConfigurationPropertyKey.PROXY_META_DATA_COLLECTOR_ENABLED.getKey(),
Boolean.TRUE.toString()));
+ when(metaData.getTemporaryProps()).thenReturn(new
TemporaryConfigurationProperties(props));
+
when(contextManager.getMetaDataContexts().getMetaData()).thenReturn(metaData);
+
when(metaData.getAllDatabases()).thenReturn(Collections.singleton(database));
+ when(database.getName()).thenReturn("foo_db");
+ when(database.getProtocolType()).thenReturn(databaseType);
+
when(database.getAllSchemas()).thenReturn(Collections.singleton(schema));
+ when(schema.getName()).thenReturn("public");
+
when(DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class,
databaseType)).thenReturn(Optional.of(collector));
+ ExclusiveOperatorEngine exclusiveOperatorEngine =
contextManager.getExclusiveOperatorEngine();
+ doAnswer(invocation -> {
+
invocation.<ExclusiveOperationVoidCallback>getArgument(2).execute();
+ return null;
+
}).when(exclusiveOperatorEngine).operate(any(RefreshStatisticsOperation.class),
eq(5000L), any(ExclusiveOperationVoidCallback.class));
+ }
+
+ @Test
+ void assertRefreshWithDatabaseRemovedAfterEnumeration() {
+ ShardingSphereTable table = new ShardingSphereTable("foo_table",
Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
+ when(schema.getAllTables()).thenReturn(Collections.singleton(table));
+ new StatisticsRefreshEngine(contextManager).refresh();
+ verify(collector).collectRowColumnValues("foo_db", "public",
"foo_table", metaData);
+ verify(contextManager, never()).getPersistServiceFacade();
+ }
+
+ @Test
+ void assertRefreshContinuesAfterCollectionFailure() {
+ ShardingSphereTable firstTable = new
ShardingSphereTable("first_table", Collections.emptyList(),
Collections.emptyList(), Collections.emptyList());
+ ShardingSphereTable secondTable = new
ShardingSphereTable("second_table", Collections.emptyList(),
Collections.emptyList(), Collections.emptyList());
+ when(schema.getAllTables()).thenReturn(Arrays.asList(firstTable,
secondTable));
+ when(collector.collectRowColumnValues("foo_db", "public",
"first_table", metaData)).thenThrow(new IllegalStateException("Collection
failed."));
+ new StatisticsRefreshEngine(contextManager).refresh();
+ verify(collector).collectRowColumnValues("foo_db", "public",
"first_table", metaData);
+ verify(collector).collectRowColumnValues("foo_db", "public",
"second_table", metaData);
+ verify(contextManager, never()).getPersistServiceFacade();
+ }
+}
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutor.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutor.java
index 2ba716b4ade..6f4042f3c90 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutor.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutor.java
@@ -28,7 +28,6 @@ import
org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.JDBCDriv
import org.apache.shardingsphere.infra.executor.sql.process.ProcessEngine;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.session.query.QueryContext;
-import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
import
org.apache.shardingsphere.proxy.backend.connector.DatabaseProxyConnector;
import
org.apache.shardingsphere.proxy.backend.connector.jdbc.executor.callback.ProxyJDBCExecutorCallbackFactory;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
@@ -66,8 +65,7 @@ public final class ProxyJDBCExecutor {
public List<ExecuteResult> execute(final QueryContext queryContext, final
ExecutionGroupContext<JDBCExecutionUnit> executionGroupContext,
final boolean isReturnGeneratedKeys,
final boolean isExceptionThrown) throws SQLException {
try {
- MetaDataContexts metaDataContexts =
ProxyContext.getInstance().getContextManager().getMetaDataContexts();
- ShardingSphereDatabase database =
metaDataContexts.getMetaData().getDatabase(connectionSession.getUsedDatabaseName());
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getDatabase(connectionSession.getUsedDatabaseName());
DatabaseType protocolType = database.getProtocolType();
processEngine.executeSQL(executionGroupContext, queryContext);
SQLStatementContext context =
queryContext.getSqlStatementContext();
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutorTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutorTest.java
index 79e1a2171eb..0873c4f3b76 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutorTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/jdbc/executor/ProxyJDBCExecutorTest.java
@@ -18,6 +18,7 @@
package org.apache.shardingsphere.proxy.backend.connector.jdbc.executor;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
import
org.apache.shardingsphere.infra.executor.kernel.model.ExecutionGroupContext;
import
org.apache.shardingsphere.infra.executor.kernel.model.ExecutionGroupReportContext;
@@ -25,6 +26,7 @@ import
org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.J
import
org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
import
org.apache.shardingsphere.infra.executor.sql.execute.result.ExecuteResult;
import
org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.JDBCDriverType;
+import org.apache.shardingsphere.infra.executor.sql.process.ProcessEngine;
import org.apache.shardingsphere.infra.executor.sql.process.ProcessRegistry;
import
org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
import org.apache.shardingsphere.infra.session.query.QueryContext;
@@ -45,9 +47,15 @@ import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
class ProxyJDBCExecutorTest {
@@ -75,8 +83,8 @@ class ProxyJDBCExecutorTest {
ProxyJDBCExecutorCallback secondCallback =
mock(ProxyJDBCExecutorCallback.class);
List<ExecuteResult> expected =
Collections.singletonList(mock(ExecuteResult.class));
try (MockedStatic<ProxyJDBCExecutorCallbackFactory> mockedStatic =
mockStatic(ProxyJDBCExecutorCallbackFactory.class)) {
- ResourceMetaData resourceMetaData =
contextManager.getMetaDataContexts().getMetaData().getDatabase("logic_db").getResourceMetaData();
- DatabaseType protocolType =
contextManager.getMetaDataContexts().getMetaData().getDatabase("logic_db").getProtocolType();
+ ResourceMetaData resourceMetaData =
contextManager.getDatabase("logic_db").getResourceMetaData();
+ DatabaseType protocolType =
contextManager.getDatabase("logic_db").getProtocolType();
mockedStatic.when(() ->
ProxyJDBCExecutorCallbackFactory.newInstance(type, protocolType,
resourceMetaData, sqlStatement, databaseProxyConnector, true, false, true))
.thenReturn(firstCallback);
mockedStatic.when(() ->
ProxyJDBCExecutorCallbackFactory.newInstance(type, protocolType,
resourceMetaData, sqlStatement, databaseProxyConnector, true, false, false))
@@ -92,6 +100,52 @@ class ProxyJDBCExecutorTest {
}
}
+ @Test
+ void assertExecuteWithUnknownDatabase() throws
ReflectiveOperationException {
+ Object originalContextManager =
Plugins.getMemberAccessor().get(ProxyContext.class.getDeclaredField("contextManager"),
ProxyContext.getInstance());
+ ContextManager contextManager = mock(ContextManager.class);
+ try {
+ ProxyContext.init(contextManager);
+ UnknownDatabaseException expected = new
UnknownDatabaseException("foo_db");
+ when(contextManager.getDatabase("foo_db")).thenThrow(expected);
+ ConnectionSession connectionSession =
mock(ConnectionSession.class);
+ when(connectionSession.getUsedDatabaseName()).thenReturn("foo_db");
+ JDBCExecutor jdbcExecutor = mock(JDBCExecutor.class);
+ ProxyJDBCExecutor executor = new
ProxyJDBCExecutor(JDBCDriverType.STATEMENT, connectionSession,
mock(DatabaseProxyConnector.class), jdbcExecutor);
+ ProcessEngine processEngine = mock(ProcessEngine.class);
+
Plugins.getMemberAccessor().set(ProxyJDBCExecutor.class.getDeclaredField("processEngine"),
executor, processEngine);
+ ExecutionGroupContext<JDBCExecutionUnit> executionGroupContext =
new ExecutionGroupContext<>(Collections.emptyList(), new
ExecutionGroupReportContext("foo_pid", "foo_db"));
+ assertThat(assertThrows(UnknownDatabaseException.class, () ->
executor.execute(mock(QueryContext.class), executionGroupContext, false,
true)), sameInstance(expected));
+ verify(processEngine).completeSQLExecution("foo_pid");
+ verifyNoInteractions(jdbcExecutor);
+ } finally {
+
Plugins.getMemberAccessor().set(ProxyContext.class.getDeclaredField("contextManager"),
ProxyContext.getInstance(), originalContextManager);
+ }
+ }
+
+ @Test
+ void assertExecuteWithSQLException() throws SQLException,
ReflectiveOperationException {
+ Object originalContextManager =
Plugins.getMemberAccessor().get(ProxyContext.class.getDeclaredField("contextManager"),
ProxyContext.getInstance());
+ ContextManager contextManager = mock(ContextManager.class,
RETURNS_DEEP_STUBS);
+ try {
+ ProxyContext.init(contextManager);
+ ConnectionSession connectionSession =
mock(ConnectionSession.class);
+ when(connectionSession.getUsedDatabaseName()).thenReturn("foo_db");
+ JDBCExecutor jdbcExecutor = mock(JDBCExecutor.class);
+ ProxyJDBCExecutor executor = new
ProxyJDBCExecutor(JDBCDriverType.STATEMENT, connectionSession,
mock(DatabaseProxyConnector.class), jdbcExecutor);
+ ProcessEngine processEngine = mock(ProcessEngine.class);
+
Plugins.getMemberAccessor().set(ProxyJDBCExecutor.class.getDeclaredField("processEngine"),
executor, processEngine);
+ ExecutionGroupContext<JDBCExecutionUnit> executionGroupContext =
new ExecutionGroupContext<>(Collections.emptyList(), new
ExecutionGroupReportContext("foo_pid", "foo_db"));
+ SQLException expected = new SQLException("foo execution failure");
+ when(jdbcExecutor.execute(eq(executionGroupContext), any(),
any())).thenThrow(expected);
+ QueryContext queryContext =
mockQueryContext(mock(SQLStatement.class));
+ assertThat(assertThrows(SQLException.class, () ->
executor.execute(queryContext, executionGroupContext, false, true)),
sameInstance(expected));
+ verify(processEngine).completeSQLExecution("foo_pid");
+ } finally {
+
Plugins.getMemberAccessor().set(ProxyContext.class.getDeclaredField("contextManager"),
ProxyContext.getInstance(), originalContextManager);
+ }
+ }
+
private QueryContext mockQueryContext(final SQLStatement sqlStatement) {
QueryContext result = mock(QueryContext.class);
when(result.getSql()).thenReturn("SELECT 1");
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateProxyBackendHandlerTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateProxyBackendHandlerTest.java
index c097e70499b..d255b05ffa3 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateProxyBackendHandlerTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateProxyBackendHandlerTest.java
@@ -122,7 +122,6 @@ class DistSQLUpdateProxyBackendHandlerTest {
when(resourceMetaData.getStorageUnits()).thenReturn(Collections.singletonMap("ds_0",
mock(StorageUnit.class)));
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
- when(database.containsSchema(new
IdentifierValue("foo_db"))).thenReturn(true);
when(database.getSchema(new
IdentifierValue("foo_db"))).thenReturn(schema);
when(database.getResourceMetaData()).thenReturn(resourceMetaData);
when(contextManager.getDatabase("foo_db")).thenReturn(database);
@@ -136,7 +135,8 @@ class DistSQLUpdateProxyBackendHandlerTest {
ResourceMetaData resourceMetaData = mock(ResourceMetaData.class);
when(resourceMetaData.getStorageUnits()).thenReturn(Collections.singletonMap("ds_0",
mock(StorageUnit.class)));
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
-
when(database.containsSchema(any(IdentifierValue.class))).thenReturn(true);
+ when(database.getDefaultSchemaName()).thenReturn("foo_schema");
+ when(database.getSchema(new
IdentifierValue("foo_schema"))).thenReturn(mock(ShardingSphereSchema.class));
when(database.getResourceMetaData()).thenReturn(resourceMetaData);
when(contextManager.getDatabase("foo_db")).thenReturn(database);
RefreshTableMetaDataStatement sqlStatement = new
RefreshTableMetaDataStatement();
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
index 995097837fa..b845dd8cee8 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
@@ -108,7 +108,8 @@ class ExportStorageNodesExecutorTest {
@Test
void assertExecuteWithWrongDatabaseName() {
- assertThrows(IllegalArgumentException.class, () ->
executor.getRows(new ExportStorageNodesStatement("foo", null),
mockEmptyContextManager()));
+ IllegalArgumentException actual =
assertThrows(IllegalArgumentException.class, () -> executor.getRows(new
ExportStorageNodesStatement("foo", null), mockEmptyContextManager()));
+ assertThat(actual.getMessage(), is("database foo is not existed"));
}
@Test
@@ -146,6 +147,16 @@ class ExportStorageNodesExecutorTest {
assertThat(row.getCell(3), is(loadExpectedRow()));
}
+ @Test
+ void assertExecuteWhenDatabaseDropped() {
+ prepareNormalDatabase();
+ ContextManager contextManager = mock(ContextManager.class,
RETURNS_DEEP_STUBS);
+
when(contextManager.getMetaDataContexts().getMetaData().getDatabase("normal_db")).thenReturn(database,
null);
+ Collection<LocalDataQueryResultRow> actual = executor.getRows(new
ExportStorageNodesStatement("normal_db", null), contextManager);
+ assertThat(actual.size(), is(1));
+ assertThat(actual.iterator().next().getCell(3), is(loadExpectedRow()));
+ }
+
@Test
void assertExecuteWithFilePath() throws IOException {
prepareNormalDatabase();
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/refresh/RefreshTableMetaDataExecutorTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/refresh/RefreshTableMetaDataExecutorTest.java
index f823d96c687..d8e062848d5 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/refresh/RefreshTableMetaDataExecutorTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/refresh/RefreshTableMetaDataExecutorTest.java
@@ -37,7 +37,6 @@ import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -96,6 +95,19 @@ class RefreshTableMetaDataExecutorTest {
verify(contextManager).reloadDatabase(database);
}
+ @Test
+ void assertExecuteUpdateWhenSchemaDropped() {
+ ShardingSphereDatabase database = mockDatabase(true);
+ ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
+ when(schema.getName()).thenReturn("Foo_Schema");
+ when(schema.containsTable(new
IdentifierValue("foo_table"))).thenReturn(true);
+ when(database.getSchema(new
IdentifierValue("foo_schema"))).thenReturn(schema, null);
+ ContextManager contextManager = mock(ContextManager.class);
+ executor.setDatabase(database);
+ executor.executeUpdate(new RefreshTableMetaDataStatement(new
IdentifierValue("foo_table"), null, new IdentifierValue("foo_schema")),
contextManager);
+ verify(contextManager).reloadTable(database, "Foo_Schema", new
IdentifierValue("foo_table"));
+ }
+
@Test
void assertExecuteUpdateWithEmptyStorageUnits() {
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
@@ -139,8 +151,7 @@ class RefreshTableMetaDataExecutorTest {
ShardingSphereDatabase result = mock(ShardingSphereDatabase.class,
RETURNS_DEEP_STUBS);
when(result.getName()).thenReturn("logic_db");
when(result.getResourceMetaData().getStorageUnits()).thenReturn(Collections.singletonMap("ds_0",
mock(StorageUnit.class)));
- when(result.containsSchema(anyString())).thenReturn(schemaExists);
-
when(result.containsSchema(any(IdentifierValue.class))).thenReturn(schemaExists);
+
when(result.getSchema(any(IdentifierValue.class))).thenReturn(schemaExists ?
mock(ShardingSphereSchema.class) : null);
return result;
}
}
diff --git
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
index 443c9494b02..3468a5dc376 100644
---
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
+++
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
@@ -17,6 +17,7 @@
package
org.apache.shardingsphere.proxy.frontend.firebird.command.query.statement.prepare;
+import com.google.common.base.Suppliers;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.database.connector.firebird.metadata.data.FirebirdBlobInfoRegistry;
@@ -48,6 +49,7 @@ import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectS
import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.UpdateStatementContext;
import org.apache.shardingsphere.infra.binder.engine.SQLBindEngine;
import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
+import
org.apache.shardingsphere.infra.exception.kernel.metadata.TableNotFoundException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
@@ -100,6 +102,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
+import java.util.function.Supplier;
/**
* Firebird prepare transaction command executor.
@@ -129,7 +132,7 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
}
FirebirdServerPreparedStatement serverPreparedStatement = new
FirebirdServerPreparedStatement(packet.getSQL(), sqlStatementContext,
packet.getHintValueContext());
connectionSession.getServerPreparedStatementRegistry().addPreparedStatement(statementId,
serverPreparedStatement);
- return createResponse(sqlStatementContext, metaDataContexts);
+ return createResponse(sqlStatementContext);
}
private SQLStatement resolveCurrentDatabase(final SQLStatement
sqlStatement) {
@@ -145,7 +148,7 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
return packet.isValidStatementHandle() ? packet.getStatementId() :
FirebirdStatementIdGenerator.getInstance().getStatementId(connectionSession.getConnectionId());
}
- private Collection<DatabasePacket> createResponse(final
SQLStatementContext sqlStatementContext, final MetaDataContexts
metaDataContexts) {
+ private Collection<DatabasePacket> createResponse(final
SQLStatementContext sqlStatementContext) {
FirebirdSQLInfoReturnValue statementType =
getFirebirdStatementType(sqlStatementContext.getSqlStatement());
FirebirdPrepareStatementReturnPacket returnPacket = new
FirebirdPrepareStatementReturnPacket();
while (packet.nextItem()) {
@@ -155,14 +158,14 @@ public final class
FirebirdPrepareStatementCommandExecutor implements CommandExe
break;
case SELECT:
if (statementType.isSelectDescribable()) {
- processDescribe(sqlStatementContext, metaDataContexts,
returnPacket.getDescribeSelect(), true);
+ processDescribe(sqlStatementContext,
returnPacket.getDescribeSelect(), true);
} else {
skipDescribe();
}
break;
case BIND:
if (statementType.isBindDescribable()) {
- processDescribe(sqlStatementContext, metaDataContexts,
returnPacket.getDescribeBind(), false);
+ processDescribe(sqlStatementContext,
returnPacket.getDescribeBind(), false);
} else {
skipDescribe();
}
@@ -223,39 +226,34 @@ public final class
FirebirdPrepareStatementCommandExecutor implements CommandExe
}
}
- private void processDescribe(final SQLStatementContext
sqlStatementContext, final MetaDataContexts metaDataContexts, final
Collection<FirebirdReturnColumnPacket> describeColumns,
- final boolean returnAll) {
+ private void processDescribe(final SQLStatementContext
sqlStatementContext, final Collection<FirebirdReturnColumnPacket>
describeColumns, final boolean returnAll) {
// TODO add exception if the first item is not DESCRIBE_VARS
packet.nextItem();
Collection<FirebirdSQLInfoPacketType> requestedItems = new
LinkedList<>();
while (packet.nextItem()) {
requestedItems.add(packet.getCurrentItem());
if (packet.getCurrentItem() ==
FirebirdSQLInfoPacketType.DESCRIBE_END) {
+ Supplier<ShardingSphereDatabase> database =
Suppliers.memoize(() ->
ProxyContext.getInstance().getContextManager().getDatabase(connectionSession.getCurrentDatabaseName()));
+ Supplier<Optional<ShardingSphereSchema>> schema =
Suppliers.memoize(() -> database.get().findDefaultSchema());
if (returnAll) {
- processReturnValues(sqlStatementContext, metaDataContexts,
describeColumns, requestedItems);
+ processReturnValues(sqlStatementContext, database, schema,
describeColumns, requestedItems);
} else {
- processParameters(sqlStatementContext, metaDataContexts,
describeColumns, requestedItems);
+ processParameters(sqlStatementContext, database, schema,
describeColumns, requestedItems);
}
return;
}
}
}
- private void processReturnValues(final SQLStatementContext
sqlStatementContext, final MetaDataContexts metaDataContexts, final
Collection<FirebirdReturnColumnPacket> describeColumns,
+ private void processReturnValues(final SQLStatementContext
sqlStatementContext, final Supplier<ShardingSphereDatabase> database,
+ final
Supplier<Optional<ShardingSphereSchema>> schema, final
Collection<FirebirdReturnColumnPacket> describeColumns,
final
Collection<FirebirdSQLInfoPacketType> requestedItems) {
- String databaseName = connectionSession.getCurrentDatabaseName();
- ShardingSphereDatabase database =
metaDataContexts.getMetaData().getDatabase(databaseName);
- ShardingSphereSchema schema =
database.findDefaultSchema().orElse(null);
- Collection<Projection> projections =
getProjections(sqlStatementContext, schema);
+ Collection<Projection> projections =
getProjections(sqlStatementContext, database, schema);
int columnCount = 0;
for (Projection each : projections) {
if (each instanceof ColumnProjection) {
String tableName = ((ColumnProjection)
each).getOriginalTable().getValue();
- ShardingSphereTable table =
schema.getTable(tableName.isEmpty() ?
getTableNames(sqlStatementContext).iterator().next() : tableName);
- if (null == table) {
- table =
metaDataContexts.getMetaData().getDatabase(databaseName).getSchema("system_tables")
- .getTable(tableName.isEmpty() ?
getTableNames(sqlStatementContext).iterator().next() : tableName);
- }
+ ShardingSphereTable table = getTable(tableName.isEmpty() ?
getTableNames(sqlStatementContext).iterator().next() : tableName, database,
schema);
ShardingSphereColumn column =
table.getColumn(((ColumnProjection) each).getOriginalColumn().getValue());
processColumn(describeColumns, requestedItems, table, column,
((ColumnProjection) each).getOwner().orElse(null),
each.getAlias().orElse(null), ++columnCount);
} else if (each instanceof ExpressionProjection) {
@@ -270,7 +268,8 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
}
}
- private Collection<Projection> getProjections(final SQLStatementContext
sqlStatementContext, final ShardingSphereSchema schema) {
+ private Collection<Projection> getProjections(final SQLStatementContext
sqlStatementContext, final Supplier<ShardingSphereDatabase> database,
+ final
Supplier<Optional<ShardingSphereSchema>> schema) {
if (sqlStatementContext instanceof SelectStatementContext) {
SelectStatementContext selectStatement = (SelectStatementContext)
sqlStatementContext;
Collection<Projection> expandProjections =
selectStatement.getProjectionsContext().getExpandProjections();
@@ -298,7 +297,7 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
for (ProjectionSegment each : projections) {
Projection projection =
projectionEngine.createProjection(each).orElse(null);
if (projection instanceof ShorthandProjection) {
- result.addAll(processShorthandProjection(sqlStatementContext,
schema, (ShorthandProjection) projection));
+ result.addAll(processShorthandProjection(sqlStatementContext,
database, schema, (ShorthandProjection) projection));
} else if (!(projection instanceof DerivedProjection) && null !=
projection) {
result.add(projection);
}
@@ -306,7 +305,8 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
return result;
}
- private Collection<Projection> processShorthandProjection(final
SQLStatementContext sqlStatementContext, final ShardingSphereSchema schema,
final ShorthandProjection projection) {
+ private Collection<Projection> processShorthandProjection(final
SQLStatementContext sqlStatementContext, final Supplier<ShardingSphereDatabase>
database,
+ final
Supplier<Optional<ShardingSphereSchema>> schema, final ShorthandProjection
projection) {
if (!projection.getActualColumns().isEmpty()) {
return projection.getActualColumns();
}
@@ -314,7 +314,7 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
TablesContext tablesContext = sqlStatementContext.getTablesContext();
if (null != tablesContext) {
for (String tableName : tablesContext.getTableNames()) {
- ShardingSphereTable table = schema.getTable(tableName);
+ ShardingSphereTable table = getTable(tableName, database,
schema);
table.getAllColumns().forEach(each -> {
ColumnSegmentBoundInfo info = new
ColumnSegmentBoundInfo(null, new IdentifierValue(table.getName()), new
IdentifierValue(each.getName()), TableSourceType.PHYSICAL_TABLE);
result.add(new ColumnProjection(null, new
IdentifierValue(each.getName()), null,
sqlStatementContext.getSqlStatement().getDatabaseType(), null, null, info));
@@ -324,19 +324,28 @@ public final class
FirebirdPrepareStatementCommandExecutor implements CommandExe
return result;
}
- private void processParameters(final SQLStatementContext
sqlStatementContext, final MetaDataContexts metaDataContexts, final
Collection<FirebirdReturnColumnPacket> describeColumns,
+ @HighFrequencyInvocation
+ private ShardingSphereTable getTable(final String tableName, final
Supplier<ShardingSphereDatabase> database, final
Supplier<Optional<ShardingSphereSchema>> schema) {
+ ShardingSphereTable result = schema.get().map(optional ->
optional.getTable(tableName)).orElse(null);
+ if (null == result) {
+ result =
database.get().getSchema("system_tables").getTable(tableName);
+ }
+ ShardingSpherePreconditions.checkNotNull(result, () -> new
TableNotFoundException(tableName));
+ return result;
+ }
+
+ private void processParameters(final SQLStatementContext
sqlStatementContext, final Supplier<ShardingSphereDatabase> database,
+ final
Supplier<Optional<ShardingSphereSchema>> schema, final
Collection<FirebirdReturnColumnPacket> describeColumns,
final Collection<FirebirdSQLInfoPacketType>
requestedItems) {
if (sqlStatementContext instanceof InsertStatementContext) {
- processInsertStatement((InsertStatementContext)
sqlStatementContext, metaDataContexts, describeColumns, requestedItems);
+ processInsertStatement((InsertStatementContext)
sqlStatementContext, database, schema, describeColumns, requestedItems);
return;
}
Collection<ColumnSegment> affectedColumns =
findAffectedColumns(sqlStatementContext);
int parametersCount =
sqlStatementContext.getSqlStatement().getParameterMarkers().size();
- String databaseName = connectionSession.getCurrentDatabaseName();
- ShardingSphereSchema schema =
metaDataContexts.getMetaData().getDatabase(databaseName).findDefaultSchema().orElse(null);
int columnCount = 0;
for (ColumnSegment columnSegment : affectedColumns) {
- ShardingSphereTable table =
schema.getTable(columnSegment.getColumnBoundInfo().getOriginalTable().getValue());
+ ShardingSphereTable table =
getTable(columnSegment.getColumnBoundInfo().getOriginalTable().getValue(),
database, schema);
ShardingSphereColumn column =
table.getColumn(columnSegment.getColumnBoundInfo().getOriginalColumn().getValue());
processColumn(describeColumns, requestedItems, table, column,
columnSegment.getOwner().map(OwnerSegment::getIdentifier).orElse(null),
columnSegment.getIdentifier(), ++columnCount);
}
@@ -345,18 +354,17 @@ public final class
FirebirdPrepareStatementCommandExecutor implements CommandExe
}
}
- private void processInsertStatement(final InsertStatementContext
sqlStatementContext, final MetaDataContexts metaDataContexts, final
Collection<FirebirdReturnColumnPacket> describeColumns,
+ private void processInsertStatement(final InsertStatementContext
sqlStatementContext, final Supplier<ShardingSphereDatabase> database,
+ final
Supplier<Optional<ShardingSphereSchema>> schema, final
Collection<FirebirdReturnColumnPacket> describeColumns,
final
Collection<FirebirdSQLInfoPacketType> requestedItems) {
Collection<String> tableNames = getTableNames(sqlStatementContext);
Collection<String> affectedColumns = new LinkedList<>();
for (InsertValueContext context :
sqlStatementContext.getInsertValueContexts()) {
affectedColumns.addAll(processInsertValueContext(sqlStatementContext, context));
}
- String databaseName = connectionSession.getCurrentDatabaseName();
- ShardingSphereSchema schema =
metaDataContexts.getMetaData().getDatabase(databaseName).findDefaultSchema().orElse(null);
int columnCount = 0;
for (String tableName : tableNames) {
- ShardingSphereTable table = schema.getTable(tableName);
+ ShardingSphereTable table = getTable(tableName, database, schema);
for (String columnName : affectedColumns) {
ShardingSphereColumn column = table.getColumn(columnName);
processColumn(describeColumns, requestedItems, table, column,
null, null, ++columnCount);
@@ -518,7 +526,7 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
@HighFrequencyInvocation
private String getActualTableName(final String logicTableName) {
- ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase(connectionSession.getCurrentDatabaseName());
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getDatabase(connectionSession.getCurrentDatabaseName());
for (DataNodeRuleAttribute each :
database.getRuleMetaData().getAttributes(DataNodeRuleAttribute.class)) {
Optional<String> actualTableName =
each.findFirstActualTable(logicTableName);
if (actualTableName.isPresent()) {
diff --git
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
index 8f3249ff0cb..dee52e8336d 100644
---
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
+++
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
@@ -20,6 +20,7 @@ package
org.apache.shardingsphere.proxy.frontend.firebird.command.query.statemen
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.database.connector.firebird.metadata.data.FirebirdBlobInfoRegistry;
import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.NoDatabaseSelectedException;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import
org.apache.shardingsphere.database.protocol.firebird.packet.command.query.FirebirdBinaryColumnType;
import
org.apache.shardingsphere.database.protocol.firebird.packet.command.query.info.type.sql.FirebirdSQLInfoPacketType;
import
org.apache.shardingsphere.database.protocol.firebird.packet.command.query.info.type.sql.FirebirdSQLInfoReturnValue;
@@ -31,6 +32,7 @@ import
org.apache.shardingsphere.database.protocol.firebird.payload.FirebirdPack
import org.apache.shardingsphere.database.protocol.packet.DatabasePacket;
import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import
org.apache.shardingsphere.infra.exception.kernel.metadata.TableNotFoundException;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
@@ -65,6 +67,9 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoSettings;
@@ -75,12 +80,15 @@ import java.sql.Types;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import java.util.Properties;
+import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
+import static org.hamcrest.Matchers.sameInstance;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doReturn;
@@ -131,6 +139,8 @@ class FirebirdPrepareStatementCommandExecutorTest {
when(packet.getCurrentItem()).thenReturn(FirebirdSQLInfoPacketType.STMT_TYPE);
MetaDataContexts metaDataContexts = createMetaDataContexts();
when(ProxyContext.getInstance().getContextManager().getMetaDataContexts()).thenReturn(metaDataContexts);
+
when(ProxyContext.getInstance().getContextManager().getDatabase("foo_db")).thenReturn(metaDataContexts.getMetaData().getDatabase("foo_db"));
+
when(ProxyContext.getInstance().getContextManager().getDatabase(null)).thenThrow(NoDatabaseSelectedException.class);
}
@AfterEach
@@ -339,4 +349,196 @@ class FirebirdPrepareStatementCommandExecutorTest {
executor.execute();
verify(connectionSession).invalidatePreparedStatementCache(FirebirdStatementResourceCleaner.createPreparedStatementCacheKey(1));
}
+
+ @Test
+ void assertDescribeLiteralWithoutDatabase() throws Exception {
+ when(connectionSession.getCurrentDatabaseName()).thenReturn(null);
+ mockDescribeRequest(FirebirdSQLInfoPacketType.SELECT);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeSelect().size(), is(1));
+ FirebirdPacketPayload payload = mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeSelect().get(0).write(payload);
+ verify(payload).writeInt4LE(FirebirdBinaryColumnType.LONG.getValue() +
1);
+ }
+
+ private void mockDescribeRequest(final FirebirdSQLInfoPacketType
describeType) {
+ when(packet.nextItem()).thenReturn(true, true, true, true, true,
false);
+
when(packet.getCurrentItem()).thenReturn(FirebirdSQLInfoPacketType.STMT_TYPE,
describeType, FirebirdSQLInfoPacketType.TYPE, FirebirdSQLInfoPacketType.TYPE,
+ FirebirdSQLInfoPacketType.DESCRIBE_END,
FirebirdSQLInfoPacketType.DESCRIBE_END);
+ }
+
+ @Test
+ void assertDescribeParameterWithoutDatabase() throws Exception {
+ when(connectionSession.getCurrentDatabaseName()).thenReturn(null);
+ when(packet.getSQL()).thenReturn("SELECT ?");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.BIND);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeBind().size(), is(1));
+ FirebirdPacketPayload payload = mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeBind().get(0).write(payload);
+
verify(payload).writeInt4LE(FirebirdBinaryColumnType.VARYING.getValue() + 1);
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("describeTableArguments")
+ void assertDescribeTable(final String name, final String sql, final
boolean defaultSchemaPresent, final FirebirdBinaryColumnType columnType) throws
Exception {
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getDatabase("foo_db");
+ addSystemSchema(database);
+ if (!defaultSchemaPresent) {
+ database.dropSchema("foo_db");
+ doReturn(Optional.empty()).when(database).findDefaultSchema();
+ }
+ when(packet.getSQL()).thenReturn(sql);
+ mockDescribeRequest(FirebirdSQLInfoPacketType.SELECT);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeSelect().size(), is(1));
+ FirebirdPacketPayload payload = mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeSelect().get(0).write(payload);
+ verify(payload).writeInt4LE(columnType.getValue() + 1);
+ }
+
+ private void addSystemSchema(final ShardingSphereDatabase database) {
+ ShardingSphereColumn column = new
ShardingSphereColumn("RDB$RELATION_ID", Types.SMALLINT, false, false, false,
true, false, true);
+ ShardingSphereTable table = new ShardingSphereTable("RDB$DATABASE",
Collections.singleton(column), Collections.emptyList(),
Collections.emptyList());
+ database.addSchema(new ShardingSphereSchema("system_tables",
databaseType, Collections.singleton(table), Collections.emptyList()));
+ }
+
+ private static Stream<Arguments> describeTableArguments() {
+ return Stream.of(
+ Arguments.of("Default schema table", "SELECT id FROM foo_tbl",
true, FirebirdBinaryColumnType.LONG),
+ Arguments.of("System table with default schema", "SELECT
RDB$RELATION_ID FROM RDB$DATABASE", true, FirebirdBinaryColumnType.SHORT),
+ Arguments.of("System table without default schema", "SELECT
RDB$RELATION_ID FROM RDB$DATABASE", false, FirebirdBinaryColumnType.SHORT));
+ }
+
+ @Test
+ void assertDescribeSystemTableParameterWithoutDefaultSchema() throws
Exception {
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getDatabase("foo_db");
+ addSystemSchema(database);
+ database.dropSchema("foo_db");
+ doReturn(Optional.empty()).when(database).findDefaultSchema();
+ when(packet.getSQL()).thenReturn("SELECT RDB$RELATION_ID FROM
RDB$DATABASE WHERE RDB$RELATION_ID = ?");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.BIND);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeBind().size(), is(1));
+ FirebirdPacketPayload payload = mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeBind().get(0).write(payload);
+ verify(payload).writeInt4LE(FirebirdBinaryColumnType.SHORT.getValue()
+ 1);
+ }
+
+ @Test
+ void assertDescribeInsertParameter() throws Exception {
+ when(packet.getSQL()).thenReturn("INSERT INTO foo_tbl (id) VALUES
(?)");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.BIND);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeBind().size(), is(1));
+ FirebirdPacketPayload payload = mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeBind().get(0).write(payload);
+ verify(payload).writeInt4LE(FirebirdBinaryColumnType.LONG.getValue() +
1);
+ }
+
+ @Test
+ void assertDescribeReturningShorthand() throws Exception {
+ when(packet.getSQL()).thenReturn("INSERT INTO foo_tbl (id) VALUES (1)
RETURNING *");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.SELECT);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeSelect().size(), is(2));
+ FirebirdPacketPayload idPayload = mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeSelect().get(0).write(idPayload);
+ verify(idPayload).writeInt4LE(FirebirdBinaryColumnType.LONG.getValue()
+ 1);
+ FirebirdPacketPayload contentPayload =
mock(FirebirdPacketPayload.class);
+ actualReturnPacket.getDescribeSelect().get(1).write(contentPayload);
+
verify(contentPayload).writeInt4LE(FirebirdBinaryColumnType.BLOB.getValue() +
1);
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("describeWithSchemaReplacementArguments")
+ void assertDescribeWithSchemaReplacement(final String name, final String
sql, final FirebirdSQLInfoPacketType describeType) throws Exception {
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase("foo_db");
+ ShardingSphereColumn idColumn = new ShardingSphereColumn("id",
Types.INTEGER, false, false, true, true, false, true);
+ ShardingSphereColumn codeColumn = new ShardingSphereColumn("code",
Types.BIGINT, false, false, true, true, false, true);
+ ShardingSphereTable originalTable = new ShardingSphereTable("foo_tbl",
Arrays.asList(idColumn, codeColumn), Collections.emptyList(),
Collections.emptyList());
+ database.addSchema(new ShardingSphereSchema("foo_db", databaseType,
Collections.singleton(originalTable), Collections.emptyList()));
+ when(database.findDefaultSchema()).thenCallRealMethod();
+ ShardingSphereTable replacementTable = new
ShardingSphereTable("foo_tbl", Collections.singleton(idColumn),
Collections.emptyList(), Collections.emptyList());
+ ShardingSphereSchema replacementSchema = new
ShardingSphereSchema("foo_db", databaseType,
Collections.singleton(replacementTable), Collections.emptyList());
+
when(ProxyContext.getInstance().getContextManager().getDatabase("foo_db")).thenReturn(database).thenAnswer(invocation
-> {
+ database.addSchema(replacementSchema);
+ return database;
+ }).thenReturn(database);
+ when(packet.getSQL()).thenReturn(sql);
+ when(packet.nextItem()).thenReturn(true, true, true, true, true, true,
false);
+
when(packet.getCurrentItem()).thenReturn(FirebirdSQLInfoPacketType.STMT_TYPE,
describeType, FirebirdSQLInfoPacketType.TYPE, FirebirdSQLInfoPacketType.TYPE,
+ FirebirdSQLInfoPacketType.FIELD,
FirebirdSQLInfoPacketType.FIELD, FirebirdSQLInfoPacketType.DESCRIBE_END,
FirebirdSQLInfoPacketType.DESCRIBE_END);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ List<FirebirdReturnColumnPacket> actualColumns =
FirebirdSQLInfoPacketType.BIND == describeType ?
actualReturnPacket.getDescribeBind() : actualReturnPacket.getDescribeSelect();
+ assertThat(actualColumns.size(), is(2));
+ FirebirdPacketPayload idPayload = mock(FirebirdPacketPayload.class);
+ when(idPayload.getCharset()).thenReturn(StandardCharsets.UTF_8);
+ actualColumns.get(0).write(idPayload);
+ verify(idPayload).writeBytes("id".getBytes(StandardCharsets.UTF_8));
+ verify(idPayload).writeInt4LE(FirebirdBinaryColumnType.LONG.getValue()
+ 1);
+ FirebirdPacketPayload codePayload = mock(FirebirdPacketPayload.class);
+ when(codePayload.getCharset()).thenReturn(StandardCharsets.UTF_8);
+ actualColumns.get(1).write(codePayload);
+
verify(codePayload).writeBytes("code".getBytes(StandardCharsets.UTF_8));
+
verify(codePayload).writeInt4LE(FirebirdBinaryColumnType.INT64.getValue() + 1);
+ }
+
+ private static Stream<Arguments> describeWithSchemaReplacementArguments() {
+ return Stream.of(
+ Arguments.of("Select columns", "SELECT id, code FROM foo_tbl",
FirebirdSQLInfoPacketType.SELECT),
+ Arguments.of("Bind parameters", "SELECT id, code FROM foo_tbl
WHERE id = ? AND code = ?", FirebirdSQLInfoPacketType.BIND),
+ Arguments.of("Returning shorthand", "INSERT INTO foo_tbl (id,
code) VALUES (1, 2) RETURNING *", FirebirdSQLInfoPacketType.SELECT));
+ }
+
+ @Test
+ void assertDescribeWithDatabaseRemoved() {
+ when(packet.getSQL()).thenReturn("SELECT id FROM foo_tbl");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.SELECT);
+ UnknownDatabaseException expected = new
UnknownDatabaseException("foo_db");
+
when(ProxyContext.getInstance().getContextManager().getDatabase("foo_db")).thenThrow(expected);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ assertThat(assertThrows(UnknownDatabaseException.class,
executor::execute), sameInstance(expected));
+ }
+
+ @Test
+ void assertDescribeBlobWithDatabaseRemoved() {
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getDatabase("foo_db");
+ when(packet.getSQL()).thenReturn("SELECT content FROM foo_tbl");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.SELECT);
+ UnknownDatabaseException expected = new
UnknownDatabaseException("foo_db");
+
when(ProxyContext.getInstance().getContextManager().getDatabase("foo_db")).thenReturn(database).thenThrow(expected);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ assertThat(assertThrows(UnknownDatabaseException.class,
executor::execute), sameInstance(expected));
+ }
+
+ @Test
+ void assertDescribeWithTableRemoved() {
+ ShardingSphereDatabase database =
ProxyContext.getInstance().getContextManager().getDatabase("foo_db");
+ addSystemSchema(database);
+ when(packet.getSQL()).thenReturn("SELECT id FROM foo_tbl");
+ mockDescribeRequest(FirebirdSQLInfoPacketType.SELECT);
+
when(ProxyContext.getInstance().getContextManager().getDatabase("foo_db")).thenAnswer(invocation
-> {
+ database.getSchema("foo_db").removeTable("foo_tbl");
+ return database;
+ });
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ TableNotFoundException actual =
assertThrows(TableNotFoundException.class, executor::execute);
+ assertThat(actual.getMessage(), is("Table or view 'foo_tbl' does not
exist."));
+ }
+
}