This is an automated email from the ASF dual-hosted git repository.
ibessonov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 64d2e89ebb5 IGNITE-24631 Implement zone related methods in
ExecutionDistributionProvider (#5292)
64d2e89ebb5 is described below
commit 64d2e89ebb5c34edc06a5c073e4b8c548643f86c
Author: Ivan Zlenko <[email protected]>
AuthorDate: Mon Mar 3 15:44:18 2025 +0500
IGNITE-24631 Implement zone related methods in
ExecutionDistributionProvider (#5292)
---
.../exec/ExecutableTableRegistrySelfTest.java | 11 +-
.../sql/engine/framework/ClusterZoneBuilder.java | 43 +++++
.../engine/framework/ClusterZoneBuilderImpl.java | 82 +++++++++
.../sql/engine/framework/TestBuilders.java | 198 +++++++++++++++++++--
.../sql/engine/framework/ZoneBuilderBase.java | 50 ++++++
5 files changed, 370 insertions(+), 14 deletions(-)
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java
index 4ecd76ff1b5..a7b8f71ec51 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java
@@ -61,7 +61,6 @@ import org.mockito.junit.jupiter.MockitoExtension;
*/
@ExtendWith(MockitoExtension.class)
public class ExecutableTableRegistrySelfTest extends BaseIgniteAbstractTest {
-
@Mock
private ReplicaService replicaService;
@@ -158,7 +157,15 @@ public class ExecutableTableRegistrySelfTest extends
BaseIgniteAbstractTest {
when(descriptor.spliterator()).thenReturn(Spliterators.emptySpliterator());
IgniteTable sqlTable = new IgniteTableImpl(
- "TBL1", tableId, tableVersion, descriptor,
ImmutableIntList.of(0), new TestStatistic(1_000.0), Map.of(), 1, 10000
+ "TBL1",
+ tableId,
+ tableVersion,
+ descriptor,
+ ImmutableIntList.of(0),
+ new TestStatistic(1_000.0),
+ Map.of(),
+ 1,
+ 10000
);
when(sqlSchemaManager.table(schemaVersion,
tableId)).thenReturn(sqlTable);
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterZoneBuilder.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterZoneBuilder.java
new file mode 100644
index 00000000000..59665c5db64
--- /dev/null
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterZoneBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ignite.internal.sql.engine.framework;
+
+import org.apache.ignite.internal.catalog.CatalogCommand;
+import
org.apache.ignite.internal.sql.engine.framework.TestBuilders.ClusterBuilder;
+import
org.apache.ignite.internal.sql.engine.framework.TestBuilders.NestedBuilder;
+
+/**
+ * A builder interface for creating a test zone as a nested object within a
test cluster.
+ *
+ * <p>
+ * This builder allows the configuration and construction of test zones, which
are integral parts of the {@link TestCluster}.
+ * Test zones can be customized and linked to the enclosing cluster through
this builder.
+ * </p>
+ *
+ * <p>
+ * The {@link ClusterZoneBuilder} extends {@link ZoneBuilderBase}, inheriting
common methods for zone configuration,
+ * and implements {@link NestedBuilder} to ensure fluent integration into the
cluster creation process.
+ * </p>
+ *
+ * @see TestCluster
+ * @see ZoneBuilderBase
+ * @see NestedBuilder
+ */
+public interface ClusterZoneBuilder extends
ZoneBuilderBase<ClusterZoneBuilder>, NestedBuilder<ClusterBuilder> {
+ CatalogCommand build();
+}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterZoneBuilderImpl.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterZoneBuilderImpl.java
new file mode 100644
index 00000000000..f1b6a52087e
--- /dev/null
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterZoneBuilderImpl.java
@@ -0,0 +1,82 @@
+/*
+ * 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.ignite.internal.sql.engine.framework;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.catalog.CatalogCommand;
+import org.apache.ignite.internal.catalog.commands.CreateZoneCommand;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
+import
org.apache.ignite.internal.sql.engine.framework.TestBuilders.ClusterBuilder;
+import
org.apache.ignite.internal.sql.engine.framework.TestBuilders.ClusterBuilderImpl;
+
+/**
+ * An implementation of the {@link ClusterZoneBuilder} interface.
+ *
+ * <p>
+ * This class provides the concrete functionality for building and configuring
a test zone nested within a cluster.
+ * It enables the creation of zones through a fluent API, adhering to the
contract defined by {@link ClusterZoneBuilder}.
+ * </p>
+ *
+ * @see ClusterZoneBuilder
+ */
+class ClusterZoneBuilderImpl implements ClusterZoneBuilder {
+ private final ClusterBuilderImpl parent;
+
+ private String name;
+
+ private List<String> storageProfiles;
+
+ ClusterZoneBuilderImpl(ClusterBuilderImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public ClusterBuilder end() {
+ parent.zoneBuilders().add(this);
+
+ return parent;
+ }
+
+ @Override
+ public ClusterZoneBuilder name(String name) {
+ this.name = name;
+
+ return this;
+ }
+
+ @Override
+ public ClusterZoneBuilder storageProfiles(List<String> storageProfiles) {
+ this.storageProfiles = new ArrayList<>(storageProfiles);
+
+ return this;
+ }
+
+ @Override
+ public CatalogCommand build() {
+ List<StorageProfileParams> storageProfileParams =
storageProfiles.stream()
+ .map(profileName ->
StorageProfileParams.builder().storageProfile(profileName).build())
+ .collect(Collectors.toList());
+
+ return CreateZoneCommand.builder()
+ .zoneName(name)
+ .storageProfilesParams(storageProfileParams)
+ .build();
+ }
+}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
index a1049afbbe7..e9707b08348 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.sql.engine.framework;
import static java.util.UUID.randomUUID;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static
org.apache.ignite.internal.lang.IgniteSystemProperties.enabledColocation;
import static
org.apache.ignite.internal.sql.engine.exec.ExecutionServiceImplTest.PLANNING_THREAD_COUNT;
import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
@@ -159,8 +160,6 @@ import org.jetbrains.annotations.Nullable;
* A collection of builders to create test objects.
*/
public class TestBuilders {
- private static final int ZONE_ID = 10000;
-
private static final AtomicInteger TABLE_ID_GEN = new AtomicInteger();
private static final IgniteLogger LOG =
Loggers.forClass(TestBuilders.class);
@@ -375,6 +374,19 @@ public class TestBuilders {
*/
ClusterBuilder operationKillHandlers(OperationKillHandler... handlers);
+ /**
+ * Creates a new builder for defining and adding a zone to the cluster.
+ *
+ * <p>
+ * The zone builder provides a fluent API
+ * to configure various zone-related attributes before adding it to
the cluster configuration.
+ * It allows for incremental setup of the zone's properties such as
name, storage profiles, and other settings.
+ * </p>
+ *
+ * @return An instance of the {@link ClusterZoneBuilder}, enabling the
construction of a new zone.
+ */
+ ClusterZoneBuilder addZone();
+
/**
* Creates a table builder to add to the cluster.
*
@@ -407,10 +419,29 @@ public class TestBuilders {
ClusterBuilder defaultDataProvider(DefaultDataProvider
defaultDataProvider);
/**
- * Provides implementation of table with given name.
+ * Sets the default implementation of the {@link
DefaultZoneAssignmentsProvider}.
*
- * @param defaultAssignmentsProvider Name of the table given instance
represents.
- * @return {@code this} for chaining.
+ * <p>
+ * This method allows specifying a {@link
DefaultZoneAssignmentsProvider} instance to define
+ * how default zone assignments are handled within the cluster during
tests.
+ * This configuration influences the assignment logic for zones,
ensuring proper setup and behavior in testing scenarios.
+ * </p>
+ *
+ * @param defaultZoneAssignmentsProvider The {@link
DefaultZoneAssignmentsProvider} instance to configure.
+ * This instance determines the
management of default zone assignments.
+ * @return {@code this}, enabling method chaining for fluent
configuration.
+ */
+ ClusterBuilder
defaultZoneAssignmentsProvider(DefaultZoneAssignmentsProvider
defaultZoneAssignmentsProvider);
+
+ /**
+ * Configures a default implementation of the {@link
DefaultAssignmentsProvider}.
+ *
+ * <p>This method allows specifying a {@link
DefaultAssignmentsProvider} instance
+ * to be used during the creation of a test cluster.
+ * The provided instance determines how default assignments are
managed within the cluster during its setup and operation.
+ *
+ * @param defaultAssignmentsProvider The {@link
DefaultAssignmentsProvider} instance to be applied.
+ * @return {@code this}, to allow method chaining.
*/
ClusterBuilder defaultAssignmentsProvider(DefaultAssignmentsProvider
defaultAssignmentsProvider);
@@ -452,6 +483,9 @@ public class TestBuilders {
/** Sets id for the table. The caller must guarantee that provided id
is unique. */
TableBuilder tableId(int id);
+ /** Sets zone id for the table. */
+ TableBuilder zoneId(int id);
+
/** Sets the number of partitions fot this table. Default value is
equal to {@link CatalogUtils#DEFAULT_PARTITION_COUNT}. */
TableBuilder partitions(int num);
@@ -624,7 +658,8 @@ public class TestBuilders {
}
}
- private static class ClusterBuilderImpl implements ClusterBuilder {
+ static class ClusterBuilderImpl implements ClusterBuilder {
+ private final List<ClusterZoneBuilder> zoneBuilders = new
ArrayList<>();
private final List<ClusterTableBuilderImpl> tableBuilders = new
ArrayList<>();
private List<String> nodeNames;
private final List<SystemView<?>> systemViews = new ArrayList<>();
@@ -635,6 +670,7 @@ public class TestBuilders {
private OperationKillHandler @Nullable [] killHandlers = null;
private @Nullable DefaultDataProvider defaultDataProvider = null;
+ private @Nullable DefaultZoneAssignmentsProvider
defaultZoneAssignmentsProvider = null;
private @Nullable DefaultAssignmentsProvider
defaultAssignmentsProvider = null;
/** {@inheritDoc} */
@@ -664,6 +700,11 @@ public class TestBuilders {
return this;
}
+ @Override
+ public ClusterZoneBuilder addZone() {
+ return new ClusterZoneBuilderImpl(this);
+ }
+
/** {@inheritDoc} */
@Override
public ClusterTableBuilder addTable() {
@@ -690,6 +731,13 @@ public class TestBuilders {
return this;
}
+ @Override
+ public ClusterBuilder
defaultZoneAssignmentsProvider(DefaultZoneAssignmentsProvider
defaultZoneAssignmentsProvider) {
+ this.defaultZoneAssignmentsProvider =
defaultZoneAssignmentsProvider;
+
+ return this;
+ }
+
@Override
public ClusterBuilder
defaultAssignmentsProvider(DefaultAssignmentsProvider
defaultAssignmentsProvider) {
this.defaultAssignmentsProvider = defaultAssignmentsProvider;
@@ -768,6 +816,15 @@ public class TestBuilders {
ConcurrentMap<String, ScannableTable> dataProvidersByTableName =
new ConcurrentHashMap<>();
ConcurrentMap<String, UpdatableTable> updatableTablesByName = new
ConcurrentHashMap<>();
+
+ ConcurrentMap<Integer, AssignmentsProvider>
zoneAssignmentsProviderByZoneId = new ConcurrentHashMap<>();
+ zoneAssignmentsProviderByZoneId.put(
+ Blackhole.ZONE_ID,
+ (partCount, ignored) -> IntStream.range(0, partCount)
+ .mapToObj(partNo -> nodeNames)
+ .collect(Collectors.toList())
+ );
+
ConcurrentMap<String, AssignmentsProvider>
assignmentsProviderByTableName = new ConcurrentHashMap<>();
assignmentsProviderByTableName.put(
@@ -783,6 +840,11 @@ public class TestBuilders {
var systemViewManager = new
SystemViewManagerImpl(name, catalogManager);
var executionProvider = new
TestExecutionDistributionProvider(
systemViewManager::owningNodes,
+ zoneId -> resolveZoneProvider(
+ zoneId,
+ zoneAssignmentsProviderByZoneId,
+ defaultZoneAssignmentsProvider != null
? defaultZoneAssignmentsProvider::get : null
+ ),
tableName -> resolveProvider(
tableName,
assignmentsProviderByTableName,
@@ -845,6 +907,10 @@ public class TestBuilders {
}
private void initAction(CatalogManager catalogManager) {
+ List<CatalogCommand> initialZones = zoneBuilders.stream()
+ .map(ClusterZoneBuilder::build)
+ .collect(Collectors.toList());
+
List<CatalogCommand> initialSchema = tableBuilders.stream()
.flatMap(builder -> builder.build().stream())
.collect(Collectors.toList());
@@ -875,9 +941,24 @@ public class TestBuilders {
};
catalogManager.listen(CatalogEvent.INDEX_CREATE,
EventListener.fromConsumer(createIndexHandler));
+ // Init zones
+ await(catalogManager.execute(initialZones));
+
// Init schema.
await(catalogManager.execute(initialSchema));
}
+
+ /**
+ * Retrieves a list of {@link ClusterZoneBuilder} instances already
defined for the test cluster.
+ *
+ * <p>This method provides access to the builders for zones that have
been previously added during the test cluster setup.
+ * Each {@link ClusterZoneBuilder} instance represents the
configuration for a specific zone within the test cluster.
+ *
+ * @return A list of {@link ClusterZoneBuilder} instances representing
the predefined zones for the test cluster.
+ */
+ List<ClusterZoneBuilder> zoneBuilders() {
+ return zoneBuilders;
+ }
}
private static SqlSchemaManagerImpl createSqlSchemaManager(CatalogManager
catalogManager, ConcurrentMap<String, Long> tablesSize) {
@@ -896,6 +977,8 @@ public class TestBuilders {
}
private static class TableBuilderImpl implements TableBuilder {
+ private int zoneId = Blackhole.ZONE_ID;
+
private final List<AbstractTableIndexBuilderImpl<?>> indexBuilders =
new ArrayList<>();
private final List<ColumnDescriptor> columns = new ArrayList<>();
@@ -990,6 +1073,13 @@ public class TestBuilders {
return this;
}
+ @Override
+ public TableBuilder zoneId(int id) {
+ this.zoneId = id;
+
+ return this;
+ }
+
/** {@inheritDoc} */
@Override
public TableBuilder partitions(int num) {
@@ -1040,7 +1130,7 @@ public class TestBuilders {
new TestStatistic(size),
indexes,
partitions,
- ZONE_ID
+ zoneId
);
}
}
@@ -1465,7 +1555,7 @@ public class TestBuilders {
* </pre>
*/
@FunctionalInterface
- private interface NestedBuilder<ParentT> {
+ interface NestedBuilder<ParentT> {
/**
* Notifies the builder's chain of the nested builder that we need to
return back to the previous layer.
*
@@ -1611,6 +1701,8 @@ public class TestBuilders {
/** A builder to create instances of {@link
ExecutionDistributionProvider}. */
public static final class ExecutionDistributionProviderBuilder {
+ private final Map<Integer, List<List<String>>> owningNodesByZone = new
HashMap<>();
+
private final Map<String, List<List<String>>> owningNodesByTableName =
new HashMap<>();
private Function<String, List<String>> owningNodesBySystemViewName =
(n) -> null;
@@ -1621,6 +1713,19 @@ public class TestBuilders {
}
+ /**
+ * Adds table-to-node mappings to the internal list.
+ *
+ * <p>
+ * This method updates the internal mapping by associating tables with
specific nodes.
+ * It allows for defining or extending the relationships between
tables and the nodes they are mapped to within the cluster.
+ * </p>
+ */
+ public ExecutionDistributionProviderBuilder addZones(Map<Integer,
List<List<String>>> zones) {
+ this.owningNodesByZone.putAll(zones);
+ return this;
+ }
+
/** Adds tables to list of nodes mapping. */
public ExecutionDistributionProviderBuilder addTables(Map<String,
List<List<String>>> tables) {
this.owningNodesByTableName.putAll(tables);
@@ -1644,8 +1749,21 @@ public class TestBuilders {
/** Creates an instance of {@link ExecutionDistributionProvider}. */
public ExecutionDistributionProvider build() {
+ Map<Integer, List<List<String>>> owningNodesByZone =
Map.copyOf(this.owningNodesByZone);
+
Map<String, List<List<String>>> owningNodesByTableName =
Map.copyOf(this.owningNodesByTableName);
+ Function<Integer, AssignmentsProvider> zoneSourceProviderFunction
= zoneId ->
+ (AssignmentsProvider) (partitionsCount, includeBackups) ->
{
+ List<List<String>> assignments =
owningNodesByZone.get(zoneId);
+
+ if (nullOrEmpty(assignments)) {
+ throw new AssertionError("Assignments are not
configured for zone " + zoneId);
+ }
+
+ return assignments;
+ };
+
Function<String, AssignmentsProvider> sourceProviderFunction =
tableName ->
(AssignmentsProvider) (partitionsCount, includeBackups) ->
{
List<List<String>> assignments =
owningNodesByTableName.get(tableName);
@@ -1659,6 +1777,7 @@ public class TestBuilders {
return new TestExecutionDistributionProvider(
owningNodesBySystemViewName,
+ zoneSourceProviderFunction,
sourceProviderFunction,
useTablePartitions
);
@@ -1668,16 +1787,20 @@ public class TestBuilders {
private static class TestExecutionDistributionProvider implements
ExecutionDistributionProvider {
final Function<String, List<String>> owningNodesBySystemViewName;
+ final Function<Integer, AssignmentsProvider> owningNodesByZone;
+
final Function<String, AssignmentsProvider> owningNodesByTableName;
final boolean useTablePartitions;
private TestExecutionDistributionProvider(
Function<String, List<String>> owningNodesBySystemViewName,
+ Function<Integer, AssignmentsProvider> owningNodesByZone,
Function<String, AssignmentsProvider> owningNodesByTableName,
boolean useTablePartitions
) {
this.owningNodesBySystemViewName = owningNodesBySystemViewName;
+ this.owningNodesByZone = owningNodesByZone;
this.owningNodesByTableName = owningNodesByTableName;
this.useTablePartitions = useTablePartitions;
}
@@ -1695,18 +1818,35 @@ public class TestBuilders {
IgniteTable table,
boolean includeBackups
) {
- AssignmentsProvider provider =
owningNodesByTableName.apply(table.name());
+ AssignmentsProvider provider;
+
+ if (enabledColocation()) {
+ provider = owningNodesByZone.apply(table.zoneId());
+ } else {
+ provider = owningNodesByTableName.apply(table.name());
+ }
+
+ return getAssignments(provider, table, includeBackups);
+ }
+ private CompletableFuture<List<TokenizedAssignments>> getAssignments(
+ AssignmentsProvider provider,
+ IgniteTable table,
+ boolean includeBackups
+ ) {
if (provider == null) {
return CompletableFuture.failedFuture(
new AssertionError("AssignmentsProvider is not
configured for table " + table.name())
);
}
- List<List<String>> owningNodes = provider.get(table.partitions(),
includeBackups);
- if (nullOrEmpty(owningNodes) || owningNodes.size() !=
table.partitions()) {
+ int partitions = table.partitions();
+
+ List<List<String>> owningNodes = provider.get(partitions,
includeBackups);
+
+ if (nullOrEmpty(owningNodes) || owningNodes.size() != partitions) {
throw new AssertionError("Configured AssignmentsProvider
returns less assignment than expected "
- + "[table=" + table.name() + ",
expectedNumberOfPartitions=" + table.partitions()
+ + "[table=" + table.name() + ",
expectedNumberOfPartitions=" + partitions
+ ", returnedAssignmentSize=" + (owningNodes == null ?
"<null>" : owningNodes.size()) + "]");
}
@@ -1786,6 +1926,24 @@ public class TestBuilders {
ScannableTable get(String tableName);
}
+ /**
+ * The default zone assignments provider used as a fallback when no
specific provider
+ * is explicitly configured via {@link
TestCluster#setAssignmentsProvider(String, AssignmentsProvider)}.
+ *
+ * <p>
+ * This provider supplies default zone assignments necessary for executing
SQL queries
+ * or simulating cluster behavior in tests where explicit zone assignment
configurations are not required.
+ * </p>
+ *
+ * <p>
+ * Typically used in scenarios where test simplicity is preferred, and
explicit zone assignment handling is unnecessary or redundant.
+ * </p>
+ */
+ @FunctionalInterface
+ public interface DefaultZoneAssignmentsProvider {
+ AssignmentsProvider get(int zoneId);
+ }
+
/**
* Assignments provider that will be used in case no other provider was
specified explicitly via
* {@link TestCluster#setAssignmentsProvider(String, AssignmentsProvider)}.
@@ -1811,6 +1969,20 @@ public class TestBuilders {
List<List<String>> get(int partitionsCount, boolean includeBackups);
}
+ private static <T> @Nullable T resolveZoneProvider(
+ int zoneId,
+ Map<Integer, T> providersByZoneId,
+ @Nullable Function<Integer, T> defaultProvider
+ ) {
+ T provider = providersByZoneId.get(zoneId);
+
+ if (provider == null && defaultProvider != null) {
+ return defaultProvider.apply(zoneId);
+ }
+
+ return provider;
+ }
+
private static <T> @Nullable T resolveProvider(
String tableName,
Map<String, T> providersByTableName,
@@ -1826,6 +1998,8 @@ public class TestBuilders {
}
private static class Blackhole implements UpdatableTable {
+ static final int ZONE_ID = 10_000;
+
static final String TABLE_NAME = "BLACKHOLE";
private static final TableDescriptor DESCRIPTOR = new
TableDescriptorImpl(
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ZoneBuilderBase.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ZoneBuilderBase.java
new file mode 100644
index 00000000000..87d706a5e22
--- /dev/null
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ZoneBuilderBase.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ignite.internal.sql.engine.framework;
+
+import java.util.List;
+
+/**
+ * Represents the base interface for describing a complete set of zone-related
fields.
+ *
+ * <p>
+ * This interface serves as a foundational aspect to ensure synchronization
between different variants of zone builders.
+ * Implementations of this interface allow the building of zone configurations
+ * with common methods that can be extended or specialized in concrete
builders.
+ * </p>
+ *
+ * @param <ChildT> The specific type of the builder implementation that will
be exposed to the user, enabling fluent builder patterns.
+ * @see ClusterZoneBuilder
+ */
+interface ZoneBuilderBase<ChildT> {
+ /**
+ * Sets the name of the zone.
+ *
+ * @param name The name to assign to the zone.
+ * @return The builder instance for chaining methods.
+ */
+ ChildT name(String name);
+
+ /**
+ * Configures the storage profiles associated with the zone.
+ *
+ * @param storageProfiles A list of storage profile names to associate
with the zone.
+ * @return The builder instance for chaining methods.
+ */
+ ChildT storageProfiles(List<String> storageProfiles);
+}