diff --git a/docs/document/content/features/sharding/limitation.cn.md b/docs/document/content/features/sharding/limitation.cn.md index d902f38d706d8..b06a67ba385b9 100644 --- a/docs/document/content/features/sharding/limitation.cn.md +++ b/docs/document/content/features/sharding/limitation.cn.md @@ -91,6 +91,10 @@ MySQL、PostgreSQL 和 openGauss 都支持 LIMIT 分页,无需子查询: SELECT * FROM t_order o ORDER BY id LIMIT ? OFFSET ? ``` +### 聚合查询 + +支持 `MAX`, `MIN`, `SUM`, `COUNT`, `AVG`, `BIT_XOR`, `GROUP_CONCAT` 聚合语法。 + ### 运算表达式中包含分片键 当分片键处于运算表达式中时,无法通过 SQL `字面` 提取用于分片的值,将导致全路由。 @@ -113,10 +117,6 @@ SELECT * FROM t_order WHERE to_date(create_time, 'yyyy-mm-dd') = '2019-01-01'; 5. 支持基于广播表和单表创建、修改和删除视图; 6. 支持 MySQL `SHOW CREATE TABLE viewName` 查看视图的创建语句。 -### 聚合查询 - -支持 MySQL `MAX`, `MIN`, `SUM`, `COUNT`, `AVG`, `BIT_XOR`, `GROUP_CONCAT` 聚合语法 - ## 实验性支持 实验性支持特指使用 Federation 执行引擎提供支持。 该引擎处于快速开发中,用户虽基本可用,但仍需大量优化,是实验性产品。 @@ -159,10 +159,10 @@ SELECT * FROM t_user u RIGHT JOIN t_user_role r ON u.user_id = r.user_id WHERE u ### CASE WHEN -以下 CASE WHEN 语句不支持: +以下 `CASE WHEN` 语句不支持: -- CASE WHEN 中包含子查询 -- CASE WHEN 中使用逻辑表名(请使用表别名) +- `CASE WHEN` 中包含子查询 +- `CASE WHEN` 中使用逻辑表名(请使用表别名) ### 分页查询 @@ -170,11 +170,11 @@ Oracle 和 SQLServer 由于分页查询较为复杂,目前有部分分页查 - Oracle -目前不支持 rownum + BETWEEN 的分页方式。 +目前不支持 `rownum + BETWEEN` 的分页方式。 - SQLServer -目前不支持使用 WITH xxx AS (SELECT …) 的方式进行分页。由于 Hibernate 自动生成的 SQLServer 分页语句使用了 WITH 语句,因此目前并不支持基于 Hibernate 的 SQLServer 分页。 目前也不支持使用两个 TOP + 子查询的方式实现分页。 +目前不支持使用 `WITH xxx AS (SELECT …)` 的方式进行分页。由于 Hibernate 自动生成的 SQLServer 分页语句使用了 `WITH` 语句,因此目前并不支持基于 Hibernate 的 SQLServer 分页。 目前也不支持使用两个 TOP + 子查询的方式实现分页。 ### LOAD DATA / LOAD XML diff --git a/docs/document/content/features/sharding/limitation.en.md b/docs/document/content/features/sharding/limitation.en.md index d60bda884762e..f70580d318d6e 100644 --- a/docs/document/content/features/sharding/limitation.en.md +++ b/docs/document/content/features/sharding/limitation.en.md @@ -85,6 +85,10 @@ SELECT * FROM t_order o ORDER BY id OFFSET ? ROW FETCH NEXT ? ROWS ONLY SELECT * FROM t_order o ORDER BY id LIMIT ? OFFSET ? ``` +### Aggregation + +Support `MAX`, `MIN`, `SUM`, `COUNT`, `AVG`, `BIT_XOR`, `GROUP_CONCAT` and so on. + ### Shard keys included in operation expressions When the sharding key is contained in an expression, the value used for sharding cannot be extracted through the SQL letters and will result in full routing. @@ -161,7 +165,7 @@ Due to the complexity of paging queries, there are currently some paging queries The paging method of rownum + BETWEEN is not supported at present - SQLServer -Currently, pagination with WITH xxx AS (SELECT ...) is not supported. Since the SQLServer paging statement automatically generated by Hibernate uses the WITH statement, Hibernate-based SQLServer paging is not supported at this moment. Pagination using two TOP + subquery also cannot be supported at this time. +Currently, pagination with `WITH xxx AS (SELECT ...)` is not supported. Since the SQLServer paging statement automatically generated by Hibernate uses the `WITH` statement, Hibernate-based SQLServer paging is not supported at this moment. Pagination using two TOP + subquery also cannot be supported at this time. ### LOAD DATA / LOAD XML diff --git a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaDataTest.java b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaDataTest.java index 7e3e0f7d365f9..f1f4a28fbc453 100644 --- a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaDataTest.java +++ b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaDataTest.java @@ -87,7 +87,7 @@ void assertDropDatabase() { ShardingSphereMetaData metaData = new ShardingSphereMetaData(new LinkedList<>(Collections.singleton(mockDatabase(resourceMetaData, dataSource, databaseRule1, databaseRule2))), mock(ResourceMetaData.class), new RuleMetaData(Collections.singleton(globalRule)), new ConfigurationProperties(new Properties())); metaData.dropDatabase("foo_db"); - assertTrue(metaData.getDatabases().isEmpty()); + assertTrue(metaData.getAllDatabases().isEmpty()); Awaitility.await().pollDelay(10L, TimeUnit.MILLISECONDS).until(dataSource::isClosed); assertTrue(dataSource.isClosed()); verify(globalRule).refresh(metaData.getAllDatabases(), GlobalRuleChangedType.DATABASE_CHANGED); diff --git a/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/MetaDataContextsFactoryTest.java b/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/MetaDataContextsFactoryTest.java index 3691e7a3d5aec..d7b31a021111b 100644 --- a/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/MetaDataContextsFactoryTest.java +++ b/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/MetaDataContextsFactoryTest.java @@ -110,8 +110,8 @@ void assertCreateWithJDBCInstanceMetaData() throws SQLException { try (MetaDataContexts actual = MetaDataContextsFactory.create(metaDataPersistService, createContextManagerBuilderParameter(), computeNodeInstanceContext)) { assertThat(actual.getMetaData().getGlobalRuleMetaData().getRules().size(), is(1)); assertThat(actual.getMetaData().getGlobalRuleMetaData().getRules().iterator().next(), instanceOf(MockedRule.class)); - assertTrue(actual.getMetaData().getDatabases().containsKey("foo_db")); - assertThat(actual.getMetaData().getDatabases().size(), is(1)); + assertTrue(actual.getMetaData().containsDatabase("foo_db")); + assertThat(actual.getMetaData().getAllDatabases().size(), is(1)); } } @@ -122,8 +122,8 @@ void assertCreateWithProxyInstanceMetaData() throws SQLException { try (MetaDataContexts actual = MetaDataContextsFactory.create(metaDataPersistService, createContextManagerBuilderParameter(), mock(ComputeNodeInstanceContext.class, RETURNS_DEEP_STUBS))) { assertThat(actual.getMetaData().getGlobalRuleMetaData().getRules().size(), is(1)); assertThat(actual.getMetaData().getGlobalRuleMetaData().getRules().iterator().next(), instanceOf(MockedRule.class)); - assertTrue(actual.getMetaData().getDatabases().containsKey("foo_db")); - assertThat(actual.getMetaData().getDatabases().size(), is(1)); + assertTrue(actual.getMetaData().containsDatabase("foo_db")); + assertThat(actual.getMetaData().getAllDatabases().size(), is(1)); } } diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java index ec307ee5b2581..5c32160ff71cb 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java @@ -18,7 +18,6 @@ package org.apache.shardingsphere.proxy.backend.handler.database; import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseCreateExistsException; -import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.mode.manager.ContextManager; import org.apache.shardingsphere.mode.metadata.MetaDataContexts; import org.apache.shardingsphere.proxy.backend.context.ProxyContext; @@ -84,7 +83,7 @@ void assertExecuteCreateExistDatabaseWithIfNotExists() throws SQLException { private ContextManager mockContextManager() { ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS); MetaDataContexts metaDataContexts = mock(MetaDataContexts.class, RETURNS_DEEP_STUBS); - when(metaDataContexts.getMetaData().getDatabases()).thenReturn(Collections.singletonMap("foo_db", mock(ShardingSphereDatabase.class))); + when(metaDataContexts.getMetaData().getAllDatabases()).thenReturn(Collections.singleton(mock())); when(result.getMetaDataContexts()).thenReturn(metaDataContexts); return result; } diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java index ff24b8c44e2f2..3ad76c398907b 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java @@ -18,8 +18,8 @@ package org.apache.shardingsphere.proxy.backend.handler.database; import org.apache.shardingsphere.authority.rule.AuthorityRule; -import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseDropNotExistsException; import org.apache.shardingsphere.infra.database.core.type.DatabaseType; +import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseDropNotExistsException; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; @@ -41,9 +41,8 @@ import org.mockito.quality.Strictness; import java.sql.SQLException; +import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; @@ -79,15 +78,15 @@ void setUp() { } private ContextManager mockContextManager() { - Map databases = new HashMap<>(2, 1F); - ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS); - databases.put("foo_db", database); - databases.put("bar_db", database); + ShardingSphereDatabase database1 = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS); + when(database1.getName()).thenReturn("foo_db"); + ShardingSphereDatabase database2 = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS); + when(database2.getName()).thenReturn("bar_db"); MetaDataContexts metaDataContexts = mock(MetaDataContexts.class, RETURNS_DEEP_STUBS); - when(metaDataContexts.getMetaData().getDatabases()).thenReturn(databases); - when(metaDataContexts.getMetaData().getDatabase("foo_db")).thenReturn(database); - when(metaDataContexts.getMetaData().getDatabase("bar_db")).thenReturn(database); - when(metaDataContexts.getMetaData().getDatabase("test_not_exist_db")).thenReturn(database); + when(metaDataContexts.getMetaData().getAllDatabases()).thenReturn(Arrays.asList(database1, database2)); + when(metaDataContexts.getMetaData().getDatabase("foo_db")).thenReturn(database1); + when(metaDataContexts.getMetaData().getDatabase("bar_db")).thenReturn(database2); + when(metaDataContexts.getMetaData().getDatabase("test_not_exist_db")).thenReturn(mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS)); when(metaDataContexts.getMetaData().getGlobalRuleMetaData()).thenReturn(new RuleMetaData(Collections.singleton(mock(AuthorityRule.class)))); ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS); when(result.getMetaDataContexts()).thenReturn(metaDataContexts); diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationExecutorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationExecutorTest.java index 178df02704720..9df98fe3b29db 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationExecutorTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationExecutorTest.java @@ -139,6 +139,7 @@ private void init(final String databaseName) { private ContextManager mockContextManager(final String databaseName) { ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS); ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS); + when(database.getName()).thenReturn(databaseName); ResourceMetaData resourceMetaData = mock(ResourceMetaData.class); when(database.getResourceMetaData()).thenReturn(resourceMetaData); when(database.getProtocolType()).thenReturn(TypedSPILoader.getService(DatabaseType.class, "FIXTURE")); @@ -148,7 +149,7 @@ private ContextManager mockContextManager(final String databaseName) { when(database.getResourceMetaData().getStorageUnits()).thenReturn(new HashMap<>(Collections.singletonMap("foo_ds", storageUnit))); when(database.getResourceMetaData().getDataSourceMap()).thenReturn(Collections.singletonMap("foo_ds", dataSource)); when(database.getRuleMetaData().getAttributes(DataSourceMapperRuleAttribute.class)).thenReturn(Collections.emptyList()); - when(result.getMetaDataContexts().getMetaData().getDatabases()).thenReturn(Collections.singletonMap(databaseName, database)); + when(result.getMetaDataContexts().getMetaData().getAllDatabases()).thenReturn(Collections.singleton(database)); when(result.getMetaDataContexts().getMetaData().getDatabase(databaseName)).thenReturn(database); when(result.getMetaDataContexts().getMetaData().getProps()).thenReturn(new ConfigurationProperties(createProperties())); return result; diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataExecutorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataExecutorTest.java index 51aa5752aab67..89c353b4e5d96 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataExecutorTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataExecutorTest.java @@ -128,10 +128,11 @@ private ContextManager mockContextManager(final String feature) { .thenReturn(new ConfigurationProperties(PropertiesBuilder.build(new Property(ConfigurationPropertyKey.PROXY_FRONTEND_DATABASE_PROTOCOL_TYPE.getKey(), "MySQL")))); if (null != feature) { ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS); + when(database.getName()).thenReturn(feature); when(database.getSchema("foo_db")).thenReturn(new ShardingSphereSchema("foo_db", createTables(), Collections.emptyList())); Map storageUnits = createStorageUnits(); when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits); - when(result.getMetaDataContexts().getMetaData().getDatabases()).thenReturn(Collections.singletonMap(feature, database)); + when(result.getMetaDataContexts().getMetaData().getAllDatabases()).thenReturn(Collections.singleton(database)); when(result.getMetaDataContexts().getMetaData().getDatabase(feature)).thenReturn(database); } return result; diff --git a/proxy/bootstrap/src/test/java/org/apache/shardingsphere/proxy/version/ShardingSphereProxyVersionTest.java b/proxy/bootstrap/src/test/java/org/apache/shardingsphere/proxy/version/ShardingSphereProxyVersionTest.java index f2c030c4a341a..7dc79d1894993 100644 --- a/proxy/bootstrap/src/test/java/org/apache/shardingsphere/proxy/version/ShardingSphereProxyVersionTest.java +++ b/proxy/bootstrap/src/test/java/org/apache/shardingsphere/proxy/version/ShardingSphereProxyVersionTest.java @@ -68,7 +68,7 @@ void assertSetVersionWhenStorageTypeDifferentWithProtocolType() throws SQLExcept private ContextManager mockContextManager(final String databaseProductName, final String databaseProductVersion) throws SQLException { ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS); ShardingSphereDatabase database = mockDatabase(databaseProductName, databaseProductVersion); - when(result.getMetaDataContexts().getMetaData().getDatabases()).thenReturn(Collections.singletonMap("foo_db", database)); + when(result.getMetaDataContexts().getMetaData().getAllDatabases()).thenReturn(Collections.singleton(database)); return result; } diff --git a/proxy/frontend/type/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/extended/describe/PostgreSQLComDescribeExecutorTest.java b/proxy/frontend/type/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/extended/describe/PostgreSQLComDescribeExecutorTest.java index b4e0a9457838c..9eb5b314a6d8e 100644 --- a/proxy/frontend/type/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/extended/describe/PostgreSQLComDescribeExecutorTest.java +++ b/proxy/frontend/type/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/extended/describe/PostgreSQLComDescribeExecutorTest.java @@ -344,8 +344,8 @@ void assertDescribeSelectPreparedStatement() throws SQLException { List parameterIndexes = IntStream.range(0, sqlStatement.getParameterCount()).boxed().collect(Collectors.toList()); ConnectionContext connectionContext = mockConnectionContext(); when(connectionSession.getConnectionContext()).thenReturn(connectionContext); - connectionSession.getServerPreparedStatementRegistry().addPreparedStatement(statementId, - new PostgreSQLServerPreparedStatement(sql, sqlStatementContext, new HintValueContext(), parameterTypes, parameterIndexes)); + connectionSession.getServerPreparedStatementRegistry().addPreparedStatement( + statementId, new PostgreSQLServerPreparedStatement(sql, sqlStatementContext, new HintValueContext(), parameterTypes, parameterIndexes)); Collection actual = executor.execute(); assertThat(actual.size(), is(2)); Iterator actualPacketsIterator = actual.iterator(); @@ -387,7 +387,6 @@ private ContextManager mockContextManager() { RuleMetaData globalRuleMetaData = new RuleMetaData(Arrays.asList( new SQLTranslatorRule(new DefaultSQLTranslatorRuleConfigurationBuilder().build()), new LoggingRule(new DefaultLoggingRuleConfigurationBuilder().build()))); when(result.getMetaDataContexts().getMetaData().getGlobalRuleMetaData()).thenReturn(globalRuleMetaData); - when(result.getMetaDataContexts().getMetaData().getDatabases()).thenReturn(Collections.singletonMap(DATABASE_NAME, mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS))); Collection columnMetaData = Arrays.asList( new ShardingSphereColumn("id", Types.INTEGER, true, false, false, true, false, false), new ShardingSphereColumn("k", Types.INTEGER, true, false, false, true, false, false), @@ -401,8 +400,7 @@ private ContextManager mockContextManager() { when(result.getMetaDataContexts().getMetaData().getDatabase(DATABASE_NAME).getProtocolType()).thenReturn(TypedSPILoader.getService(DatabaseType.class, "PostgreSQL")); StorageUnit storageUnit = mock(StorageUnit.class, RETURNS_DEEP_STUBS); when(storageUnit.getStorageType()).thenReturn(TypedSPILoader.getService(DatabaseType.class, "PostgreSQL")); - when(result.getMetaDataContexts().getMetaData().getDatabase(DATABASE_NAME).getResourceMetaData().getStorageUnits()) - .thenReturn(Collections.singletonMap("ds_0", storageUnit)); + when(result.getMetaDataContexts().getMetaData().getDatabase(DATABASE_NAME).getResourceMetaData().getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", storageUnit)); when(result.getMetaDataContexts().getMetaData().containsDatabase(DATABASE_NAME)).thenReturn(true); when(result.getMetaDataContexts().getMetaData().getDatabase(DATABASE_NAME).containsSchema("public")).thenReturn(true); when(result.getMetaDataContexts().getMetaData().getDatabase(DATABASE_NAME).getSchema("public").containsTable(TABLE_NAME)).thenReturn(true);