This is an automated email from the ASF dual-hosted git repository. mpochatkin pushed a commit to branch IGNITE-23185 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit 204726d2b0d11241bc34e476c7aa51aa539154d0 Author: Mikhail Pochatkin <[email protected]> AuthorDate: Wed Sep 25 17:56:11 2024 +0300 IGNITE-23185 Add methods to access table and zone definitions --- .../java/org/apache/ignite/catalog/ColumnType.java | 2 + .../org/apache/ignite/catalog/IgniteCatalog.java | 20 +++ .../catalog/definitions/ColumnDefinition.java | 19 +++ .../catalog/definitions/IndexDefinition.java | 20 +++ .../catalog/definitions/TableDefinition.java | 40 +++++ .../ignite/catalog/definitions/ZoneDefinition.java | 16 ++ .../lang}/DistributionZoneNotFoundException.java | 5 +- modules/catalog-dsl/build.gradle | 1 + .../ignite/internal/catalog/ItCatalogDslTest.java | 85 +++++++++- .../internal/matcher/ColumnDefinitionsMatcher.java | 43 +++++ .../internal/matcher/TableDefinitionMatcher.java | 185 +++++++++++++++++++++ .../internal/matcher/ZoneDefinitionMatcher.java | 166 ++++++++++++++++++ .../catalog/sql/CreateFromDefinitionImpl.java | 12 +- .../internal/catalog/sql/CreateTableImpl.java | 4 +- .../internal/catalog/sql/CreateZoneImpl.java | 18 +- .../internal/catalog/sql/IgniteCatalogSqlImpl.java | 159 ++++++++++++++++++ .../apache/ignite/internal/catalog/sql/Option.java | 96 +++++++++++ .../ignite/internal/catalog/sql/QueryUtils.java | 4 + .../internal/catalog/sql/SelectFromView.java | 88 ++++++++++ .../ignite/internal/catalog/sql/WithOption.java | 80 --------- .../ignite/internal/catalog/sql/QueryPartTest.java | 6 +- .../catalog/CatalogSystemViewRegistry.java | 4 +- .../systemviews/TablesSystemViewProvider.java | 172 +++++++++++++++++++ .../systemviews/ZonesSystemViewProvider.java | 51 +++++- .../java/org/apache/ignite/internal/cli/Main.java | 2 +- .../ignite/internal/client/TcpIgniteClient.java | 2 +- .../distributionzones/DistributionZoneManager.java | 2 +- .../CausalityDataNodesEngine.java | 2 +- .../DistributionZoneCausalityDataNodesTest.java | 2 +- .../threading/PublicApiThreadingIgniteCatalog.java | 21 +++ .../disaster/DisasterRecoveryManager.java | 2 +- 31 files changed, 1210 insertions(+), 119 deletions(-) diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java b/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java index 08fd08cf0a..26bb62c4bd 100644 --- a/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java +++ b/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java @@ -352,4 +352,6 @@ public class ColumnType<T> { this.length = length; return this; } + + } diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java b/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java index c4d37d9219..69362eb922 100644 --- a/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java +++ b/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java @@ -191,6 +191,22 @@ public interface IgniteCatalog { */ Table createTable(TableDefinition definition); + /** + * Returns definition of the table with provided name. + * + * @param tableName Table name. + * @return Definition of the table with provided name. + */ + CompletableFuture<TableDefinition> tableDefinitionAsync(String tableName); + + /** + * Returns definition of the table with provided name. + * + * @param tableName Table name. + * @return Definition of the table with provided name. + */ + TableDefinition tableDefinition(String tableName); + /** * Creates a query object from the zone definition. * @@ -205,6 +221,10 @@ public interface IgniteCatalog { */ void createZone(ZoneDefinition definition); + CompletableFuture<ZoneDefinition> zoneDefinitionAsync(String zoneName); + + ZoneDefinition zoneDefinition(String zoneName); + /** * Creates a {@code DROP TABLE} query object from the table definition. * diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ColumnDefinition.java b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ColumnDefinition.java index af32f8dd92..f42bbf3960 100644 --- a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ColumnDefinition.java +++ b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ColumnDefinition.java @@ -100,4 +100,23 @@ public class ColumnDefinition { public @Nullable String definition() { return definition; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ColumnDefinition that = (ColumnDefinition) o; + return Objects.equals(name, that.name) + && Objects.equals(type, that.type) + && Objects.equals(definition, that.definition); + } + + @Override + public int hashCode() { + return Objects.hash(name, type, definition); + } } diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/IndexDefinition.java b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/IndexDefinition.java index bc8f6d9fc5..6b0647fa33 100644 --- a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/IndexDefinition.java +++ b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/IndexDefinition.java @@ -18,6 +18,7 @@ package org.apache.ignite.catalog.definitions; import java.util.List; +import java.util.Objects; import org.apache.ignite.catalog.ColumnSorted; import org.apache.ignite.catalog.IndexType; import org.jetbrains.annotations.Nullable; @@ -65,4 +66,23 @@ public class IndexDefinition { public List<ColumnSorted> columns() { return columns; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IndexDefinition that = (IndexDefinition) o; + return Objects.equals(name, that.name) + && type == that.type + && Objects.equals(columns, that.columns); + } + + @Override + public int hashCode() { + return Objects.hash(name, type, columns); + } } diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/TableDefinition.java b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/TableDefinition.java index fdbccc4726..e6c0fabf50 100644 --- a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/TableDefinition.java +++ b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/TableDefinition.java @@ -206,6 +206,46 @@ public class TableDefinition { return new Builder(this); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TableDefinition that = (TableDefinition) o; + return ifNotExists == that.ifNotExists + && Objects.equals(tableName, that.tableName) + && Objects.equals(schemaName, that.schemaName) + && Objects.equals(columns, that.columns) + && pkType == that.pkType + && Objects.equals(pkColumns, that.pkColumns) + && Objects.equals(colocationColumns, that.colocationColumns) + && Objects.equals(zoneName, that.zoneName) + && Objects.equals(keyClass, that.keyClass) + && Objects.equals(valueClass, that.valueClass) + && Objects.equals(indexes, that.indexes); + } + + @Override + public int hashCode() { + return Objects.hash( + tableName, + schemaName, + ifNotExists, + columns, + pkType, + pkColumns, + colocationColumns, + zoneName, + keyClass, + valueClass, + indexes + ); + } + /** * Builder for the table definition. */ diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java index ded14aea11..605f4c2918 100644 --- a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java +++ b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java @@ -176,6 +176,22 @@ public class ZoneDefinition { return new Builder(this); } + @Override + public String toString() { + return "ZoneDefinition{" + + "zoneName='" + zoneName + '\'' + + ", ifNotExists=" + ifNotExists + + ", partitions=" + partitions + + ", replicas=" + replicas + + ", distributionAlgorithm='" + distributionAlgorithm + '\'' + + ", dataNodesAutoAdjust=" + dataNodesAutoAdjust + + ", dataNodesAutoAdjustScaleUp=" + dataNodesAutoAdjustScaleUp + + ", dataNodesAutoAdjustScaleDown=" + dataNodesAutoAdjustScaleDown + + ", filter='" + filter + '\'' + + ", storageProfiles='" + storageProfiles + '\'' + + '}'; + } + /** * Builder for the zone definition. */ diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/exception/DistributionZoneNotFoundException.java b/modules/api/src/main/java/org/apache/ignite/lang/DistributionZoneNotFoundException.java similarity index 91% rename from modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/exception/DistributionZoneNotFoundException.java rename to modules/api/src/main/java/org/apache/ignite/lang/DistributionZoneNotFoundException.java index 5e148cf135..b49232729f 100644 --- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/exception/DistributionZoneNotFoundException.java +++ b/modules/api/src/main/java/org/apache/ignite/lang/DistributionZoneNotFoundException.java @@ -15,18 +15,17 @@ * limitations under the License. */ -package org.apache.ignite.internal.distributionzones.exception; +package org.apache.ignite.lang; import static org.apache.ignite.lang.ErrorGroups.DistributionZones.ZONE_NOT_FOUND_ERR; import java.util.UUID; -import org.apache.ignite.internal.lang.IgniteInternalException; import org.jetbrains.annotations.Nullable; /** * Exception is thrown when appropriate distribution zone can`t be found. */ -public class DistributionZoneNotFoundException extends IgniteInternalException { +public class DistributionZoneNotFoundException extends IgniteException { private static final long serialVersionUID = 4690347752201656106L; /** diff --git a/modules/catalog-dsl/build.gradle b/modules/catalog-dsl/build.gradle index 5f4eff73f1..6bb7111114 100644 --- a/modules/catalog-dsl/build.gradle +++ b/modules/catalog-dsl/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation libs.jetbrains.annotations implementation project(':ignite-api') implementation project(':ignite-core') + implementation project(':ignite-catalog') testImplementation libs.hamcrest.core testImplementation testFixtures(project(':ignite-core')) diff --git a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java index d786d9d680..9b9c0377c9 100644 --- a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java +++ b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java @@ -21,6 +21,7 @@ import static org.apache.ignite.catalog.definitions.ColumnDefinition.column; import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERSIST_PROFILE_NAME; import static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.will; +import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willBe; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; @@ -31,25 +32,31 @@ import static org.hamcrest.Matchers.nullValue; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import org.apache.ignite.catalog.ColumnSorted; import org.apache.ignite.catalog.ColumnType; import org.apache.ignite.catalog.IgniteCatalog; +import org.apache.ignite.catalog.IndexType; +import org.apache.ignite.catalog.definitions.ColumnDefinition; import org.apache.ignite.catalog.definitions.TableDefinition; import org.apache.ignite.catalog.definitions.ZoneDefinition; import org.apache.ignite.internal.ClusterPerClassIntegrationTest; +import org.apache.ignite.internal.matcher.TableDefinitionMatcher; +import org.apache.ignite.internal.matcher.ZoneDefinitionMatcher; import org.apache.ignite.sql.SqlException; import org.apache.ignite.table.KeyValueView; import org.apache.ignite.table.RecordView; +import org.apache.ignite.table.Table; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @SuppressWarnings("ThrowableNotThrown") class ItCatalogDslTest extends ClusterPerClassIntegrationTest { - static final String POJO_KV_TABLE_NAME = "pojo_kv_test"; + static final String POJO_KV_TABLE_NAME = "POJO_KV_TEST"; static final String POJO_RECORD_TABLE_NAME = "pojo_record_test"; - static final String ZONE_NAME = "zone_test"; + static final String ZONE_NAME = "ZONE_TEST"; private static final int KEY = 1; @@ -190,7 +197,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { @Test void primitiveKeyKvViewFromAnnotation() throws Exception { - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(Integer.class, PojoValue.class); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(Integer.class, PojoValue.class); assertThat(tableFuture, will(not(nullValue()))); KeyValueView<Integer, PojoValue> keyValueView = tableFuture.get() @@ -202,7 +209,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { @Test void pojoKeyKvViewFromAnnotation() throws Exception { - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(PojoKey.class, PojoValue.class); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(PojoKey.class, PojoValue.class); assertThat(tableFuture, will(not(nullValue()))); KeyValueView<PojoKey, PojoValue> keyValueView = tableFuture.get() @@ -219,7 +226,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { .value(PojoValue.class) .build(); - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(definition); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(definition); assertThat(tableFuture, will(not(nullValue()))); KeyValueView<Integer, PojoValue> keyValueView = tableFuture.get().keyValueView(Integer.class, PojoValue.class); @@ -235,7 +242,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { .value(PojoValue.class) .build(); - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(definition); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(definition); assertThat(tableFuture, will(not(nullValue()))); KeyValueView<PojoKey, PojoValue> keyValueView = tableFuture.get().keyValueView(PojoKey.class, PojoValue.class); @@ -246,7 +253,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { @Test void pojoRecordViewFromAnnotation() throws Exception { - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(Pojo.class); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(Pojo.class); assertThat(tableFuture, will(not(nullValue()))); RecordView<Pojo> recordView = tableFuture.get().recordView(Pojo.class); @@ -259,7 +266,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { void pojoRecordViewFromDefinition() throws Exception { TableDefinition definition = TableDefinition.builder(POJO_RECORD_TABLE_NAME).record(Pojo.class).build(); - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(definition); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(definition); assertThat(tableFuture, will(not(nullValue()))); RecordView<Pojo> recordView = tableFuture.get().recordView(Pojo.class); @@ -270,7 +277,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { @Test void createFromAnnotationAndInsertBySql() throws Exception { - CompletableFuture<org.apache.ignite.table.Table> tableFuture = catalog().createTableAsync(Pojo.class); + CompletableFuture<Table> tableFuture = catalog().createTableAsync(Pojo.class); assertThat(tableFuture, will(not(nullValue()))); sql("insert into " + POJO_RECORD_TABLE_NAME + " (id, id_str, f_name, l_name, str) values (1, '1', 'f', 'l', 's')"); @@ -282,6 +289,66 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest { assertThat(tableFuture.get().recordView(Pojo.class).get(null, pojo), is(pojo)); } + @Test + public void createAndGetDefinitionTest() { + ZoneDefinition zoneDefinition = ZoneDefinition + .builder(ZONE_NAME) + .storageProfiles(DEFAULT_AIPERSIST_PROFILE_NAME) + .partitions(3) + .replicas(3) + .dataNodesAutoAdjustScaleDown(0) + .dataNodesAutoAdjustScaleUp(1) + .filter("$..*") + .distributionAlgorithm("distributionAlgorithm") + .build(); + + assertThat(catalog().createZoneAsync(zoneDefinition), willCompleteSuccessfully()); + + ZoneDefinition actual = catalog().zoneDefinition(ZONE_NAME); + assertThat( + actual, + ZoneDefinitionMatcher.isZoneDefinition() + .withZoneName(zoneDefinition.zoneName()) + .withPartitions(zoneDefinition.partitions()) + .withReplicas(zoneDefinition.replicas()) + .withDataNodesAutoAdjustScaleDown(zoneDefinition.dataNodesAutoAdjustScaleDown()) + .withDataNodesAutoAdjustScaleUp(zoneDefinition.dataNodesAutoAdjustScaleUp()) + .withFilter(zoneDefinition.filter()) + // TODO: https://issues.apache.org/jira/browse/IGNITE-22162 +// .withDistributionAlgorithm(zoneDefinition.distributionAlgorithm()) + ); + + ColumnDefinition column1 = column("COL1", ColumnType.INT32); + ColumnDefinition column2 = column("COL2", ColumnType.INT64); + ColumnDefinition column3 = column("COL3", ColumnType.BOOLEAN); + ColumnDefinition column4 = column("COL4", ColumnType.VARCHAR); + ColumnDefinition column5 = column("COL5", ColumnType.DECIMAL); + + + TableDefinition definition = TableDefinition.builder(POJO_KV_TABLE_NAME) + .zone(ZONE_NAME) + .columns(List.of(column1, column2, column3, column4, column5)) + .primaryKey(IndexType.HASH, ColumnSorted.column(column1.name()), ColumnSorted.column(column3.name())) + .index("INDEX_1", IndexType.HASH, ColumnSorted.column(column2.name()), ColumnSorted.column(column5.name())) + .colocateBy(column3.name()) + .build(); + + assertThat(catalog().createTableAsync(definition), willCompleteSuccessfully()); + + TableDefinition actual1 = catalog().tableDefinition(POJO_KV_TABLE_NAME); + assertThat( + actual1, + TableDefinitionMatcher.isTableDefinition() + .withTableName(definition.tableName()) + .withZoneName(definition.zoneName()) + .withColumns(definition.columns()) + .withPkType(definition.primaryKeyType()) + .withPkColumns(definition.primaryKeyColumns()) + .withIndexes(definition.indexes()) + .withColocationColumns(definition.colocationColumns()) + ); + } + private static IgniteCatalog catalog() { return CLUSTER.node(0).catalog(); } diff --git a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/ColumnDefinitionsMatcher.java b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/ColumnDefinitionsMatcher.java new file mode 100644 index 0000000000..247ad50d4d --- /dev/null +++ b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/ColumnDefinitionsMatcher.java @@ -0,0 +1,43 @@ +package org.apache.ignite.internal.matcher; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.ignite.catalog.ColumnType; +import org.apache.ignite.catalog.definitions.ColumnDefinition; +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; + +public class ColumnDefinitionsMatcher extends TypeSafeMatcher<List<ColumnDefinition>> { + + private final Map<String, ColumnDefinition> columns; + + public ColumnDefinitionsMatcher(List<ColumnDefinition> columns) { + this.columns = columns.stream().collect(Collectors.toMap(ColumnDefinition::name, Function.identity())); + } + + @Override + protected boolean matchesSafely(List<ColumnDefinition> item) { + for (ColumnDefinition actualCol : item) { + ColumnDefinition expectedCol = columns.get(actualCol.name()); + if (expectedCol == null) { + return false; + } + + ColumnType<?> actualType = actualCol.type(); + ColumnType<?> expectedType = expectedCol.type(); + if (expectedType != null && actualType != null && expectedType.type() != actualType.type()) { + return false; + } + } + + return true; + } + + @Override + public void describeTo(Description description) { + + } +} diff --git a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/TableDefinitionMatcher.java b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/TableDefinitionMatcher.java new file mode 100644 index 0000000000..e742d6f0e8 --- /dev/null +++ b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/TableDefinitionMatcher.java @@ -0,0 +1,185 @@ +package org.apache.ignite.internal.matcher; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.equalToIgnoringCase; +import static org.hamcrest.Matchers.in; + +import java.util.List; +import org.apache.ignite.catalog.ColumnSorted; +import org.apache.ignite.catalog.IndexType; +import org.apache.ignite.catalog.definitions.ColumnDefinition; +import org.apache.ignite.catalog.definitions.IndexDefinition; +import org.apache.ignite.catalog.definitions.TableDefinition; +import org.apache.ignite.internal.testframework.matchers.AnythingMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.TypeSafeMatcher; + +public class TableDefinitionMatcher extends TypeSafeMatcher<TableDefinition> { + private Matcher<String> tableNameMatcher = AnythingMatcher.anything(); + + private Matcher<String> schemaNameMatcher = AnythingMatcher.anything(); + + private Matcher<Boolean> ifNotExistsMatcher = AnythingMatcher.anything(); + + private Matcher<List<ColumnDefinition>> columnsMatcher = AnythingMatcher.anything(); + + private Matcher<IndexType> pkTypeMatcher = AnythingMatcher.anything(); + + private Matcher<List<ColumnSorted>> pkColumnsMatcher = AnythingMatcher.anything(); + + private Matcher<List<String>> colocationColumnsMatcher = AnythingMatcher.anything(); + + private Matcher<String> zoneNameMatcher = AnythingMatcher.anything(); + + private Matcher<Class<?>> keyClassMatcher = AnythingMatcher.anything(); + + private Matcher<Class<?>> valueClassMatcher = AnythingMatcher.anything(); + + private Matcher<List<IndexDefinition>> indexesMatcher = AnythingMatcher.anything(); + + public TableDefinitionMatcher withTableNameMatcher(Matcher<String> tableNameMatcher) { + this.tableNameMatcher = tableNameMatcher; + return this; + } + + public TableDefinitionMatcher withTableName(String tableName) { + return withTableNameMatcher(equalToIgnoringCase(tableName)); + } + + public TableDefinitionMatcher withSchemaNameMatcher(Matcher<String> schemaNameMatcher) { + this.schemaNameMatcher = schemaNameMatcher; + return this; + } + + public TableDefinitionMatcher withSchemaName(String schemaName) { + return withSchemaNameMatcher(equalToIgnoringCase(schemaName)); + } + + public TableDefinitionMatcher withIfNotExistsMatcher(Matcher<Boolean> ifNotExists) { + this.ifNotExistsMatcher = ifNotExists; + return this; + } + + public TableDefinitionMatcher withIfNotExists(boolean ifNotExists) { + return withIfNotExistsMatcher(equalTo(ifNotExists)); + } + + public TableDefinitionMatcher withColumnsMatcher(Matcher<List<ColumnDefinition>> columns) { + this.columnsMatcher = columns; + return this; + } + + public TableDefinitionMatcher withColumns(List<ColumnDefinition> columns) { + return withColumnsMatcher(new ColumnDefinitionsMatcher(columns)); + } + + public TableDefinitionMatcher withPkTypeMatcher(Matcher<IndexType> pkType) { + this.pkTypeMatcher = pkType; + return this; + } + + public TableDefinitionMatcher withPkType(IndexType pkType) { + return withPkTypeMatcher(equalTo(pkType)); + } + + public TableDefinitionMatcher withPkColumnsMatcher(Matcher<List<ColumnSorted>> pkColumns) { + this.pkColumnsMatcher = pkColumns; + return this; + } + + public TableDefinitionMatcher withPkColumns(List<ColumnSorted> pkColumns) { + return withPkColumnsMatcher(equalTo(pkColumns)); + } + + public TableDefinitionMatcher withColocationColumnsMatcher(Matcher<List<String>> colocationColumns) { + this.colocationColumnsMatcher = colocationColumns; + return this; + } + + public TableDefinitionMatcher withColocationColumns(List<String> colocationColumns) { + return withColocationColumnsMatcher(equalTo(colocationColumns)); + } + + public TableDefinitionMatcher withZoneNameMatcher(Matcher<String> zoneName) { + this.zoneNameMatcher = zoneName; + return this; + } + + public TableDefinitionMatcher withZoneName(String zoneName) { + return withZoneNameMatcher(equalTo(zoneName)); + } + + public TableDefinitionMatcher withKeyClassMatcher(Matcher<Class<?>> keyClass) { + this.keyClassMatcher = keyClass; + return this; + } + + public TableDefinitionMatcher withKeyClass(Class<?> keyClass) { + return withKeyClassMatcher(equalTo(keyClass)); + } + + public TableDefinitionMatcher withValueClassMatcher(Matcher<Class<?>> valueClass) { + this.valueClassMatcher = valueClass; + return this; + } + + public TableDefinitionMatcher withValueClass(Class<?> valueClass) { + return withValueClassMatcher(equalTo(valueClass)); + } + + public TableDefinitionMatcher withIndexesMatcher(Matcher<List<IndexDefinition>> indexes) { + this.indexesMatcher = indexes; + return this; + } + + public TableDefinitionMatcher withIndexes(List<IndexDefinition> indexes) { + return withIndexesMatcher(equalTo(indexes)); + } + + public static TableDefinitionMatcher isTableDefinition() { + return new TableDefinitionMatcher(); + } + + @Override + protected boolean matchesSafely(TableDefinition tableDefinition) { + return tableNameMatcher.matches(tableDefinition.tableName()) + && schemaNameMatcher.matches(tableDefinition.schemaName()) + && ifNotExistsMatcher.matches(tableDefinition.ifNotExists()) + && columnsMatcher.matches(tableDefinition.columns()) + && pkTypeMatcher.matches(tableDefinition.primaryKeyType()) + && pkColumnsMatcher.matches(tableDefinition.primaryKeyColumns()) + && colocationColumnsMatcher.matches(tableDefinition.colocationColumns()) + && zoneNameMatcher.matches(tableDefinition.zoneName()) + && keyClassMatcher.matches(tableDefinition.keyClass()) + && valueClassMatcher.matches(tableDefinition.valueClass()) + && indexesMatcher.matches(tableDefinition.indexes()); + } + + @Override + public void describeTo(Description description) { + description.appendText("Table definition with ") + .appendText("table name ").appendDescriptionOf(tableNameMatcher) + .appendText(System.lineSeparator()) + .appendText("schema name ").appendDescriptionOf(schemaNameMatcher) + .appendText(System.lineSeparator()) + .appendText("if not exists ").appendDescriptionOf(ifNotExistsMatcher) + .appendText(System.lineSeparator()) + .appendText("columns ").appendDescriptionOf(columnsMatcher) + .appendText(System.lineSeparator()) + .appendText("pk type ").appendDescriptionOf(pkTypeMatcher) + .appendText(System.lineSeparator()) + .appendText("pk columns ").appendDescriptionOf(pkColumnsMatcher) + .appendText(System.lineSeparator()) + .appendText("colocation columns ").appendDescriptionOf(columnsMatcher) + .appendText(System.lineSeparator()) + .appendText("zone name ").appendDescriptionOf(zoneNameMatcher) + .appendText(System.lineSeparator()) + .appendText("key class ").appendDescriptionOf(keyClassMatcher) + .appendText(System.lineSeparator()) + .appendText("value class ").appendDescriptionOf(valueClassMatcher) + .appendText(System.lineSeparator()) + .appendText("indexes ").appendDescriptionOf(indexesMatcher); + } +} diff --git a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/ZoneDefinitionMatcher.java b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/ZoneDefinitionMatcher.java new file mode 100644 index 0000000000..68533ab06c --- /dev/null +++ b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/matcher/ZoneDefinitionMatcher.java @@ -0,0 +1,166 @@ +package org.apache.ignite.internal.matcher; + +import static org.hamcrest.Matchers.equalTo; + +import org.apache.ignite.catalog.definitions.ZoneDefinition; +import org.apache.ignite.internal.testframework.matchers.AnythingMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +public class ZoneDefinitionMatcher extends TypeSafeMatcher<ZoneDefinition> { + private Matcher<String> zoneNameMatcher = AnythingMatcher.anything(); + + private Matcher<Boolean> ifNotExistsMatcher = AnythingMatcher.anything(); + + private Matcher<Integer> partitionsMatcher = AnythingMatcher.anything(); + + private Matcher<Integer> replicasMatcher = AnythingMatcher.anything(); + + private Matcher<String> distributionAlgorithmMatcher = AnythingMatcher.anything(); + + private Matcher<Integer> dataNodesAutoAdjustMatcher = AnythingMatcher.anything(); + + private Matcher<Integer> dataNodesAutoAdjustScaleUpMatcher = AnythingMatcher.anything(); + + private Matcher<Integer> dataNodesAutoAdjustScaleDownMatcher = AnythingMatcher.anything(); + + private Matcher<String> filterMatcher = AnythingMatcher.anything(); + + private Matcher<String> storageProfiles = AnythingMatcher.anything(); + + public ZoneDefinitionMatcher withZoneNameMatcher(Matcher<String> zoneNameMatcher) { + this.zoneNameMatcher = zoneNameMatcher; + return this; + } + + public ZoneDefinitionMatcher withZoneName(String zoneName) { + return withZoneNameMatcher(equalTo(zoneName)); + } + + public ZoneDefinitionMatcher withIfNotExistsMatcher(Matcher<Boolean> ifNotExistsMatcher) { + this.ifNotExistsMatcher = ifNotExistsMatcher; + return this; + } + + public ZoneDefinitionMatcher withIfNotExists(boolean ifNotExists) { + return withIfNotExistsMatcher(equalTo(ifNotExists)); + } + + public ZoneDefinitionMatcher withPartitionsMatcher(Matcher<Integer> partitionsMatcher) { + this.partitionsMatcher = partitionsMatcher; + return this; + } + + public ZoneDefinitionMatcher withPartitions(int partitions) { + return withPartitionsMatcher(equalTo(partitions)); + } + + public ZoneDefinitionMatcher withReplicasMatcher(Matcher<Integer> replicasMatcher) { + this.replicasMatcher = replicasMatcher; + return this; + } + + public ZoneDefinitionMatcher withReplicas(int replicas) { + return withReplicasMatcher(equalTo(replicas)); + } + + public ZoneDefinitionMatcher withDistributionAlgorithmMatcher(Matcher<String> withDistributionAlgorithmMatcher) { + this.distributionAlgorithmMatcher = withDistributionAlgorithmMatcher; + return this; + } + + public ZoneDefinitionMatcher withDistributionAlgorithm(String distributionAlgorithm) { + return withDistributionAlgorithmMatcher(equalTo(distributionAlgorithm)); + } + + public ZoneDefinitionMatcher withDataNodesAutoAdjustMatcher(Matcher<Integer> dataNodesAutoAdjustMatcher) { + this.dataNodesAutoAdjustMatcher = dataNodesAutoAdjustMatcher; + return this; + } + + public ZoneDefinitionMatcher withDataNodesAutoAdjust(int dataNodesAutoAdjust) { + return withDataNodesAutoAdjustMatcher(equalTo(dataNodesAutoAdjust)); + } + + public ZoneDefinitionMatcher withDataNodesAutoAdjustScaleUpMatcher( + Matcher<Integer> dataNodesAutoAdjustScaleUpMatcher) { + this.dataNodesAutoAdjustScaleUpMatcher = dataNodesAutoAdjustScaleUpMatcher; + return this; + } + + public ZoneDefinitionMatcher withDataNodesAutoAdjustScaleUp(int dataNodesAutoAdjustScaleUp) { + return withDataNodesAutoAdjustScaleUpMatcher(equalTo(dataNodesAutoAdjustScaleUp)); + } + + public ZoneDefinitionMatcher withDataNodesAutoAdjustScaleDownMatcher( + Matcher<Integer> dataNodesAutoAdjustScaleDownMatcher) { + this.dataNodesAutoAdjustScaleDownMatcher = dataNodesAutoAdjustScaleDownMatcher; + return this; + } + + public ZoneDefinitionMatcher withDataNodesAutoAdjustScaleDown(int dataNodesAutoAdjustScaleDown) { + return withDataNodesAutoAdjustScaleDownMatcher(equalTo(dataNodesAutoAdjustScaleDown)); + } + + public ZoneDefinitionMatcher withFilterMatcher(Matcher<String> filterMatcher) { + this.filterMatcher = filterMatcher; + return this; + } + + public ZoneDefinitionMatcher withFilter(String filter) { + return withFilterMatcher(equalTo(filter)); + } + + public ZoneDefinitionMatcher withStorageProfilesMatcher(Matcher<String> storageProfiles) { + this.storageProfiles = storageProfiles; + return this; + } + + public ZoneDefinitionMatcher withStorageProfiles(String storageProfiles) { + return withStorageProfilesMatcher(equalTo(storageProfiles)); + } + + public static ZoneDefinitionMatcher isZoneDefinition() { + return new ZoneDefinitionMatcher(); + } + + @Override + protected boolean matchesSafely(ZoneDefinition zoneDefinition) { + return zoneNameMatcher.matches(zoneDefinition.zoneName()) + && ifNotExistsMatcher.matches(zoneDefinition.ifNotExists()) + && partitionsMatcher.matches(zoneDefinition.partitions()) + && replicasMatcher.matches(zoneDefinition.replicas()) + && distributionAlgorithmMatcher.matches(zoneDefinition.distributionAlgorithm()) + && dataNodesAutoAdjustMatcher.matches(zoneDefinition.dataNodesAutoAdjust()) + && zoneNameMatcher.matches(zoneDefinition.zoneName()) + && dataNodesAutoAdjustScaleUpMatcher.matches(zoneDefinition.dataNodesAutoAdjustScaleUp()) + && dataNodesAutoAdjustScaleDownMatcher.matches(zoneDefinition.dataNodesAutoAdjustScaleDown()) + && filterMatcher.matches(zoneDefinition.filter()) + && storageProfiles.matches(zoneDefinition.storageProfiles()); + } + + @Override + public void describeTo(Description description) { + description.appendText("Zone definition with ") + .appendText("zone name ").appendDescriptionOf(zoneNameMatcher) + .appendText(System.lineSeparator()) + .appendText("if not exists ").appendDescriptionOf(ifNotExistsMatcher) + .appendText(System.lineSeparator()) + .appendText("partitions ").appendDescriptionOf(partitionsMatcher) + .appendText(System.lineSeparator()) + .appendText("replicas ").appendDescriptionOf(replicasMatcher) + .appendText(System.lineSeparator()) + .appendText("affinity ").appendDescriptionOf(distributionAlgorithmMatcher) + .appendText(System.lineSeparator()) + .appendText("data nodes auto adjust ").appendDescriptionOf(dataNodesAutoAdjustMatcher) + .appendText(System.lineSeparator()) + .appendText("data nodes auto adjust scale up ").appendDescriptionOf(dataNodesAutoAdjustScaleUpMatcher) + .appendText(System.lineSeparator()) + .appendText("data nodes auto adjust scale down ").appendDescriptionOf(dataNodesAutoAdjustScaleDownMatcher) + .appendText(System.lineSeparator()) + .appendText("filter ").appendDescriptionOf(filterMatcher) + .appendText(System.lineSeparator()) + .appendText("storage profiles ").appendDescriptionOf(storageProfiles); + } +} diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java index c5dc84dc6a..cf2863f6a8 100644 --- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java @@ -19,6 +19,7 @@ package org.apache.ignite.internal.catalog.sql; import static org.apache.ignite.internal.catalog.sql.CreateFromAnnotationsImpl.processColumns; import static org.apache.ignite.internal.catalog.sql.QueryUtils.isGreaterThanZero; +import static org.apache.ignite.internal.catalog.sql.QueryUtils.isPositive; import java.util.ArrayList; import java.util.Collection; @@ -70,20 +71,21 @@ class CreateFromDefinitionImpl extends AbstractCatalogQuery<TableZoneId> { createZone.distributionAlgorithm(def.distributionAlgorithm()); } - if (isGreaterThanZero(def.dataNodesAutoAdjust())) { + if (isPositive(def.dataNodesAutoAdjust())) { createZone.dataNodesAutoAdjust(def.dataNodesAutoAdjust()); } - if (isGreaterThanZero(def.dataNodesAutoAdjustScaleUp())) { + if (isPositive(def.dataNodesAutoAdjustScaleUp())) { createZone.dataNodesAutoAdjustScaleUp(def.dataNodesAutoAdjustScaleUp()); } - if (isGreaterThanZero(def.dataNodesAutoAdjustScaleDown())) { + if (isPositive(def.dataNodesAutoAdjustScaleDown())) { createZone.dataNodesAutoAdjustScaleDown(def.dataNodesAutoAdjustScaleDown()); } if (!StringUtils.nullOrBlank(def.filter())) { createZone.filter(def.filter()); } - + System.out.println("Create"); + System.out.println(this); return this; } @@ -130,6 +132,8 @@ class CreateFromDefinitionImpl extends AbstractCatalogQuery<TableZoneId> { createTable.addIndex(toIndexName(ix), ix.type(), ix.columns()); } } + System.out.println("Create"); + System.out.println(this); return this; } diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java index db92258fc1..d29159e8b6 100644 --- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java @@ -38,7 +38,7 @@ class CreateTableImpl extends AbstractCatalogQuery<Name> { private final List<Constraint> constraints = new ArrayList<>(); - private final List<WithOption> withOptions = new ArrayList<>(); + private final List<Option> withOptions = new ArrayList<>(); private Colocate colocate; @@ -119,7 +119,7 @@ class CreateTableImpl extends AbstractCatalogQuery<Name> { CreateTableImpl zone(String zone) { Objects.requireNonNull(zone, "Zone name must not be null."); - withOptions.add(WithOption.primaryZone(zone)); + withOptions.add(Option.primaryZone(zone)); return this; } diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java index dc426c4942..1a35774b4b 100644 --- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java @@ -29,7 +29,7 @@ class CreateZoneImpl extends AbstractCatalogQuery<Name> { private boolean ifNotExists; - private final List<WithOption> withOptions = new ArrayList<>(); + private final List<Option> withOptions = new ArrayList<>(); /** * Constructor for internal usage. @@ -60,21 +60,21 @@ class CreateZoneImpl extends AbstractCatalogQuery<Name> { CreateZoneImpl replicas(Integer n) { Objects.requireNonNull(n, "Replicas count must not be null."); - withOptions.add(WithOption.replicas(n)); + withOptions.add(Option.replicas(n)); return this; } CreateZoneImpl partitions(Integer n) { Objects.requireNonNull(n, "Partitions must not be null."); - withOptions.add(WithOption.partitions(n)); + withOptions.add(Option.partitions(n)); return this; } CreateZoneImpl distributionAlgorithm(String distributionAlgorithm) { Objects.requireNonNull(distributionAlgorithm, "Partition distribution algorithm must not be null."); - withOptions.add(WithOption.distributionAlgorithm(distributionAlgorithm)); + withOptions.add(Option.distributionAlgorithm(distributionAlgorithm)); return this; } @@ -84,35 +84,35 @@ class CreateZoneImpl extends AbstractCatalogQuery<Name> { "Timeout between node added or node left topology event itself and data nodes switch must not be null." ); - withOptions.add(WithOption.dataNodesAutoAdjust(adjust)); + withOptions.add(Option.dataNodesAutoAdjust(adjust)); return this; } CreateZoneImpl dataNodesAutoAdjustScaleUp(Integer adjust) { Objects.requireNonNull(adjust, "Timeout between node added topology event itself and data nodes switch must not be null."); - withOptions.add(WithOption.dataNodesAutoAdjustScaleUp(adjust)); + withOptions.add(Option.dataNodesAutoAdjustScaleUp(adjust)); return this; } CreateZoneImpl dataNodesAutoAdjustScaleDown(Integer adjust) { Objects.requireNonNull(adjust, "Timeout between node left topology event itself and data nodes switch must not be null."); - withOptions.add(WithOption.dataNodesAutoAdjustScaleDown(adjust)); + withOptions.add(Option.dataNodesAutoAdjustScaleDown(adjust)); return this; } CreateZoneImpl filter(String filter) { Objects.requireNonNull(filter, "Filter must not be null."); - withOptions.add(WithOption.filter(filter)); + withOptions.add(Option.filter(filter)); return this; } CreateZoneImpl storageProfiles(String storageProfiles) { Objects.requireNonNull(storageProfiles, "Storage profiles must not be null"); - withOptions.add(WithOption.storageProfiles(storageProfiles)); + withOptions.add(Option.storageProfiles(storageProfiles)); return this; } diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IgniteCatalogSqlImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IgniteCatalogSqlImpl.java index 1ee2c4a170..b558c8d1b1 100644 --- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IgniteCatalogSqlImpl.java +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IgniteCatalogSqlImpl.java @@ -17,16 +17,32 @@ package org.apache.ignite.internal.catalog.sql; +import static org.apache.ignite.internal.catalog.sql.Option.indexId; +import static org.apache.ignite.internal.catalog.sql.Option.name; +import static org.apache.ignite.internal.catalog.sql.Option.tableName; import static org.apache.ignite.internal.lang.IgniteExceptionMapperUtil.mapToPublicException; import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCause; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.stream.Collectors; +import org.apache.ignite.catalog.ColumnSorted; +import org.apache.ignite.catalog.ColumnType; import org.apache.ignite.catalog.IgniteCatalog; +import org.apache.ignite.catalog.IndexType; +import org.apache.ignite.catalog.definitions.ColumnDefinition; +import org.apache.ignite.catalog.definitions.IndexDefinition; import org.apache.ignite.catalog.definitions.TableDefinition; +import org.apache.ignite.catalog.definitions.TableDefinition.Builder; import org.apache.ignite.catalog.definitions.ZoneDefinition; import org.apache.ignite.internal.util.ExceptionUtils; +import org.apache.ignite.lang.DistributionZoneNotFoundException; +import org.apache.ignite.lang.TableNotFoundException; import org.apache.ignite.sql.IgniteSql; +import org.apache.ignite.sql.SqlRow; import org.apache.ignite.table.IgniteTables; import org.apache.ignite.table.Table; @@ -82,6 +98,69 @@ public class IgniteCatalogSqlImpl implements IgniteCatalog { return join(createTableAsync(definition)); } + @Override + public CompletableFuture<TableDefinition> tableDefinitionAsync(String tableName) { + return new SelectFromView<>(sql, "TABLES", name(tableName), row -> { + String schema = row.stringValue("SCHEMA"); + int indexId = row.intValue("PK_INDEX_ID"); + String zone = row.stringValue("ZONE"); + Builder builder = TableDefinition.builder(tableName).schema(schema).zone(zone).primaryKey(); + return new TableDefinitionBuilderWithIndexId(builder, indexId); + }).executeAsync() + .thenApply(definitions -> { + if (definitions.isEmpty()) { + throw new TableNotFoundException(tableName); + } + + assert definitions.size() == 1; + + return definitions.get(0); + }) + .thenCompose(tableDefinitionWithPkIndexId -> + new SelectFromView<>(sql, "INDEXES", tableName(tableName), row -> { + int pkIndexId = tableDefinitionWithPkIndexId.indexId; + + int indexId = row.intValue("INDEX_ID"); + String indexName = row.stringValue("INDEX_NAME"); + String columns = row.stringValue("COLUMNS"); + String type = row.stringValue("TYPE"); + + return Index.create(indexName, type, columns, indexId == pkIndexId); + }).executeAsync().thenApply(indexes -> { + Builder builder = tableDefinitionWithPkIndexId.builder; + for (Index index : indexes) { + if (index.isPkIndex) { + builder.primaryKey(index.type, index.columns); + } else { + builder.index(index.name, index.type, index.columns); + } + } + return builder; + })) + .thenCompose(tableDefinition -> new SelectFromView<>(sql, "TABLES_COLUMNS", tableName(tableName), row -> { + String columnName = row.stringValue("COLUMN_NAME"); + String type = row.stringValue("TYPE"); + int length = row.intValue("LENGTH"); + int precision = row.intValue("PRECISION"); + int scale = row.intValue("SCALE"); + boolean nullable = row.booleanValue("NULLABLE"); + + Class<?> typeClass = org.apache.ignite.sql.ColumnType.valueOf(type).javaClass(); + return ColumnDefinition.column(columnName, ColumnType.of(typeClass, length, precision, scale, nullable)); + }).executeAsync().thenApply(tableDefinition::columns)) + .thenCompose( + tableDefinition -> new SelectFromView<>(sql, "TABLES_COLOCATION_COLUMNS", tableName(tableName), + row -> row.stringValue("COLOCATION_COLUMN")) + .executeAsync() + .thenApply(colocatedColumn -> tableDefinition.colocateBy(colocatedColumn).build()) + ); + } + + @Override + public TableDefinition tableDefinition(String tableName) { + return join(tableDefinitionAsync(tableName)); + } + @Override public CompletableFuture<Void> createZoneAsync(ZoneDefinition definition) { return new CreateFromDefinitionImpl(sql) @@ -95,6 +174,30 @@ public class IgniteCatalogSqlImpl implements IgniteCatalog { join(createZoneAsync(definition)); } + @Override + public CompletableFuture<ZoneDefinition> zoneDefinitionAsync(String zoneName) { + return new SelectFromView<>(sql, "ZONES", name(zoneName), row -> toZoneDefinition(zoneName, row)) + .executeAsync() + .thenApply(zoneDefinitions -> { + if (zoneDefinitions.isEmpty()) { + throw new DistributionZoneNotFoundException(zoneName); + } + assert zoneDefinitions.size() == 1; + + return zoneDefinitions.get(0); + }) + .thenCompose( + zoneDefinition -> new SelectFromView<>(sql, "ZONE_STORAGE_PROFILES", Option.zoneName(zoneName), + row -> row.stringValue("STORAGE_PROFILE")) + .executeAsync() + .thenApply(profiles -> zoneDefinition.toBuilder().storageProfiles(String.join(",", profiles)).build())); + } + + @Override + public ZoneDefinition zoneDefinition(String zoneName) { + return join(zoneDefinitionAsync(zoneName)); + } + @Override public CompletableFuture<Void> dropTableAsync(TableDefinition definition) { return new DropTableImpl(sql) @@ -151,6 +254,51 @@ public class IgniteCatalogSqlImpl implements IgniteCatalog { join(dropZoneAsync(name)); } + private static ZoneDefinition toZoneDefinition(String zoneName, SqlRow row) { + int partitions = row.intValue("PARTITIONS"); + int replicas = row.intValue("REPLICAS"); + int dataNodesAutoAdjustScaleUp = row.intValue("DATA_NODES_AUTO_ADJUST_SCALE_UP"); + int dataNodesAutoAdjustScaleDown = row.intValue("DATA_NODES_AUTO_ADJUST_SCALE_DOWN"); + String filter = row.stringValue("DATA_NODES_FILTER"); + + return ZoneDefinition.builder(zoneName) + .partitions(partitions) + .replicas(replicas) + .dataNodesAutoAdjustScaleUp(dataNodesAutoAdjustScaleUp) + .dataNodesAutoAdjustScaleDown(dataNodesAutoAdjustScaleDown) + .filter(filter) + .build(); + } + + private static class Index { + private final String name; + + private final IndexType type; + + private final List<ColumnSorted> columns; + + private final boolean isPkIndex; + + private Index(String name, IndexType type, List<ColumnSorted> columns, boolean isPkIndex) { + this.name = name; + this.type = type; + this.columns = columns; + this.isPkIndex = isPkIndex; + } + + public static Index create(String name, String type, String columns, boolean isPkIndex) { + return new Index(name, IndexType.valueOf(type), fromRaw(columns), isPkIndex); + } + } + + private static List<ColumnSorted> fromRaw(String columns) { + return Arrays.stream(columns.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(ColumnSorted::column) + .collect(Collectors.toList()); + } + private static <R> R join(CompletableFuture<R> future) { try { return future.join(); @@ -158,4 +306,15 @@ public class IgniteCatalogSqlImpl implements IgniteCatalog { throw ExceptionUtils.sneakyThrow(mapToPublicException(unwrapCause(e))); } } + + private static class TableDefinitionBuilderWithIndexId { + private final TableDefinition.Builder builder; + + private final int indexId; + + private TableDefinitionBuilderWithIndexId(TableDefinition.Builder builder, int indexId) { + this.builder = builder; + this.indexId = indexId; + } + } } diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Option.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Option.java new file mode 100644 index 0000000000..4e224d6faf --- /dev/null +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Option.java @@ -0,0 +1,96 @@ +/* + * 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.catalog.sql; + +class Option extends QueryPart { + private final String name; + + private final Object value; + + private Option(String name, Object value) { + this.name = name; + this.value = value; + } + + public static Option primaryZone(String zone) { + return new Option("PRIMARY_ZONE", zone.toUpperCase()); + } + + public static Option partitions(Integer partitions) { + return new Option("PARTITIONS", partitions); + } + + public static Option replicas(Integer replicas) { + return new Option("REPLICAS", replicas); + } + + public static Option dataNodesAutoAdjust(Integer adjust) { + return new Option("DATA_NODES_AUTO_ADJUST", adjust); + } + + public static Option dataNodesAutoAdjustScaleUp(Integer adjust) { + return new Option("DATA_NODES_AUTO_ADJUST_SCALE_UP", adjust); + } + + public static Option dataNodesAutoAdjustScaleDown(Integer adjust) { + return new Option("DATA_NODES_AUTO_ADJUST_SCALE_DOWN", adjust); + } + + public static Option distributionAlgorithm(String distributionAlgorithm) { + return new Option("DISTRIBUTION_ALGORITHM", distributionAlgorithm); + } + + public static Option dataRegion(String dataRegion) { + return new Option("DATAREGION", dataRegion); + } + + public static Option storageProfiles(String storageProfiles) { + return new Option("STORAGE_PROFILES", storageProfiles); + } + + public static Option name(String name) { + return new Option("NAME", name); + } + + public static Option tableName(String tableName) { + return new Option("TABLE_NAME", tableName); + } + + public static Option zoneName(String zoneName) { + return new Option("ZONE_NAME", zoneName); + } + + public static Option indexId(int indexId) { + return new Option("INDEX_ID", indexId); + } + + public static Option filter(String filter) { + return new Option("DATA_NODES_FILTER", filter); + } + + @Override + protected void accept(QueryContext ctx) { + ctx.sql(name).sql("="); + boolean isNeedsQuotes = value instanceof String; + if (isNeedsQuotes) { + ctx.sql("'").sql(value.toString()).sql("'"); + } else { + ctx.sql(value.toString()); + } + } +} diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/QueryUtils.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/QueryUtils.java index f6d7de9deb..f2555fef9f 100644 --- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/QueryUtils.java +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/QueryUtils.java @@ -53,6 +53,10 @@ class QueryUtils { return n != null && n > 0; } + static boolean isPositive(Integer n) { + return n != null && n >= 0; + } + /** * Converts comma-separated string to a list of strings, leading and trailing spaces are trimmed. * diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/SelectFromView.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/SelectFromView.java new file mode 100644 index 0000000000..65313a7a7d --- /dev/null +++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/SelectFromView.java @@ -0,0 +1,88 @@ +/* + * 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.catalog.sql; + +import static org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import org.apache.ignite.sql.IgniteSql; +import org.apache.ignite.sql.SqlRow; +import org.apache.ignite.sql.async.AsyncResultSet; + +class SelectFromView<T> extends AbstractCatalogQuery<List<T>> { + private final String viewName; + + private final List<Option> whereOptions = new ArrayList<>(); + + private final Function<SqlRow, T> mapper; + + SelectFromView(IgniteSql sql, String viewName, Option whereOption, Function<SqlRow, T> mapper) { + this(sql, viewName, List.of(whereOption), mapper); + } + + SelectFromView(IgniteSql sql, String viewName, List<Option> whereOptions, Function<SqlRow, T> mapper) { + super(sql); + this.viewName = viewName; + this.whereOptions.addAll(whereOptions); + this.mapper = mapper; + } + + @Override + public CompletableFuture<List<T>> executeAsync() { + return sql.executeAsync(null, toString()).thenCompose(resultSet -> { + List<T> result = new ArrayList<>(); + return iterate(resultSet, result).thenApply(unused -> result); + }); + } + + private CompletableFuture<Void> iterate(AsyncResultSet<SqlRow> resultSet, List<T> result) { + for (SqlRow row : resultSet.currentPage()) { + result.add(mapper.apply(row)); + } + if (resultSet.hasMorePages()) { + return resultSet.fetchNextPage().thenCompose(nextPage -> iterate(nextPage, result)); + } else { + return nullCompletedFuture(); + } + } + + @Override + // Noop + protected List<T> result() { + return Collections.emptyList(); + } + + @Override + protected void accept(QueryContext ctx) { + ctx.sql("SELECT * FROM SYSTEM." + viewName + " "); + + if (!whereOptions.isEmpty()) { + ctx.sql("WHERE "); + for (Option option : whereOptions) { + option.accept(ctx); + } + } + + System.out.println("SELECT FROM VIEW"); + System.out.println(ctx.getSql()); + } +} diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java deleted file mode 100644 index 80397c6994..0000000000 --- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.catalog.sql; - -class WithOption extends QueryPart { - private final String name; - - private final Object value; - - private WithOption(String name, Object value) { - this.name = name; - this.value = value; - } - - public static WithOption primaryZone(String zone) { - return new WithOption("PRIMARY_ZONE", zone.toUpperCase()); - } - - public static WithOption partitions(Integer partitions) { - return new WithOption("PARTITIONS", partitions); - } - - public static WithOption replicas(Integer replicas) { - return new WithOption("REPLICAS", replicas); - } - - public static WithOption distributionAlgorithm(String distributionAlgorithm) { - return new WithOption("DISTRIBUTION_ALGORITHM", distributionAlgorithm); - } - - public static WithOption dataNodesAutoAdjust(Integer adjust) { - return new WithOption("DATA_NODES_AUTO_ADJUST", adjust); - } - - public static WithOption dataNodesAutoAdjustScaleUp(Integer adjust) { - return new WithOption("DATA_NODES_AUTO_ADJUST_SCALE_UP", adjust); - } - - public static WithOption dataNodesAutoAdjustScaleDown(Integer adjust) { - return new WithOption("DATA_NODES_AUTO_ADJUST_SCALE_DOWN", adjust); - } - - public static WithOption filter(String filter) { - return new WithOption("DATA_NODES_FILTER", filter); - } - - public static WithOption dataRegion(String dataRegion) { - return new WithOption("DATAREGION", dataRegion); - } - - public static WithOption storageProfiles(String storageProfiles) { - return new WithOption("STORAGE_PROFILES", storageProfiles); - } - - @Override - protected void accept(QueryContext ctx) { - ctx.sql(name).sql("="); - boolean isNeedsQuotes = value instanceof String; - if (isNeedsQuotes) { - ctx.sql("'").sql(value.toString()).sql("'"); - } else { - ctx.sql(value.toString()); - } - } -} diff --git a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java index 46e772ad6a..5b0f906108 100644 --- a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java +++ b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java @@ -138,13 +138,13 @@ class QueryPartTest { @Test void withOptionPart() { - WithOption withOption = WithOption.primaryZone("z"); + Option withOption = Option.primaryZone("z"); assertThat(sql(withOption), is("PRIMARY_ZONE='Z'")); - withOption = WithOption.partitions(1); + withOption = Option.partitions(1); assertThat(sql(withOption), is("PARTITIONS=1")); - withOption = WithOption.replicas(1); + withOption = Option.replicas(1); assertThat(sql(withOption), is("REPLICAS=1")); } diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogSystemViewRegistry.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogSystemViewRegistry.java index a9b27f1ff4..fb6b8b2e6d 100644 --- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogSystemViewRegistry.java +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogSystemViewRegistry.java @@ -22,6 +22,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import org.apache.ignite.internal.catalog.systemviews.IndexSystemViewProvider; import org.apache.ignite.internal.catalog.systemviews.SystemViewViewProvider; +import org.apache.ignite.internal.catalog.systemviews.TablesSystemViewProvider; import org.apache.ignite.internal.catalog.systemviews.ZonesSystemViewProvider; import org.apache.ignite.internal.systemview.api.SystemView; import org.apache.ignite.internal.systemview.api.SystemViewProvider; @@ -40,7 +41,8 @@ public class CatalogSystemViewRegistry implements SystemViewProvider { providers = List.of( new SystemViewViewProvider(), new IndexSystemViewProvider(), - new ZonesSystemViewProvider() + new ZonesSystemViewProvider(), + new TablesSystemViewProvider() ); } diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/TablesSystemViewProvider.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/TablesSystemViewProvider.java new file mode 100644 index 0000000000..db7054a048 --- /dev/null +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/TablesSystemViewProvider.java @@ -0,0 +1,172 @@ +/* + * 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.catalog.systemviews; + +import static org.apache.ignite.internal.type.NativeTypes.BOOLEAN; +import static org.apache.ignite.internal.type.NativeTypes.INT32; +import static org.apache.ignite.internal.type.NativeTypes.STRING; +import static org.apache.ignite.internal.type.NativeTypes.stringOf; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Flow.Publisher; +import java.util.function.Supplier; +import org.apache.ignite.internal.catalog.Catalog; +import org.apache.ignite.internal.catalog.CatalogSystemViewProvider; +import org.apache.ignite.internal.catalog.descriptors.CatalogTableColumnDescriptor; +import org.apache.ignite.internal.systemview.api.SystemView; +import org.apache.ignite.internal.systemview.api.SystemViews; +import org.apache.ignite.internal.util.SubscriptionUtils; + +/** + * Exposes information on tables. + * + * <ul> + * <li>TABLES - available tables</li> + * <li>TABLES_COLUMNS - columns of available tables.</li> + * <li>TABLES_COLOCATION_COLUMNS - colocated columns of available tables.</li> + * </ul> + */ +public class TablesSystemViewProvider implements CatalogSystemViewProvider { + private static final int SYSTEM_VIEW_STRING_COLUMN_LENGTH = Short.MAX_VALUE; + + @Override + public List<SystemView<?>> getView(Supplier<Catalog> catalogSupplier) { + return List.of( + getSystemViewView(catalogSupplier), + getSystemViewColocationColumnsView(catalogSupplier), + getSystemViewColumnsView(catalogSupplier) + ); + } + + private static SystemView<?> getSystemViewView(Supplier<Catalog> catalogSupplier) { + Iterable<Info> tablesData = () -> { + Catalog catalog = catalogSupplier.get(); + + return catalog.tables().stream().map(table -> { + String tableName = table.name(); + String schemaName = Objects.requireNonNull(catalog.schema(table.schemaId()), "Schema must be not null.").name(); + String zoneName = Objects.requireNonNull(catalog.zone(table.zoneId()), "Zone must be not null.").name(); + + int indexId = table.primaryKeyIndexId(); + + return new Info(tableName, schemaName, indexId, zoneName); + }).iterator(); + }; + + Publisher<Info> viewDataPublisher = SubscriptionUtils.fromIterable(tablesData); + + return SystemViews.<Info>clusterViewBuilder() + .name("TABLES") + .addColumn("SCHEMA", STRING, entry -> entry.schema) + .addColumn("NAME", STRING, entry -> entry.name) + .addColumn("PK_INDEX_ID", INT32, entry -> entry.pkIndexId) + .addColumn("ZONE", STRING, entry -> entry.zone) + .dataProvider(viewDataPublisher) + .build(); + } + + private static SystemView<?> getSystemViewColumnsView(Supplier<Catalog> catalogSupplier) { + Iterable<ColumnWithTableId> viewData = () -> { + Catalog catalog = catalogSupplier.get(); + + return catalog.tables().stream() + .flatMap(table -> table.columns().stream() + .map(columnDescriptor -> new ColumnWithTableId( + catalog.schema(table.schemaId()).name(), + table.name(), + columnDescriptor + ) + ) + ) + .iterator(); + }; + + Publisher<ColumnWithTableId> viewDataPublisher = SubscriptionUtils.fromIterable(viewData); + + return SystemViews.<ColumnWithTableId>clusterViewBuilder() + .name("TABLES_COLUMNS") + .addColumn("SCHEMA", STRING, entry -> entry.schema) + .addColumn("TABLE_NAME", STRING, entry -> entry.tableName) + .addColumn("COLUMN_NAME", STRING, entry -> entry.descriptor.name()) + .addColumn("TYPE", STRING, entry -> entry.descriptor.type().name()) + .addColumn("NULLABLE", BOOLEAN, entry -> entry.descriptor.nullable()) + .addColumn("PRECISION", INT32, entry -> entry.descriptor.precision()) + .addColumn("SCALE", INT32, entry -> entry.descriptor.scale()) + .addColumn("LENGTH", INT32, entry -> entry.descriptor.length()) + .dataProvider(viewDataPublisher) + .build(); + } + + private static SystemView<?> getSystemViewColocationColumnsView(Supplier<Catalog> catalogSupplier) { + Iterable<ColocationColumnsWithTable> viewData = () -> { + Catalog catalog = catalogSupplier.get(); + + return catalog.tables().stream() + .flatMap(table -> table.colocationColumns().stream() + .map(colocationColumn -> new ColocationColumnsWithTable(table.name(), colocationColumn)) + ) + .iterator(); + }; + + Publisher<ColocationColumnsWithTable> viewDataPublisher = SubscriptionUtils.fromIterable(viewData); + + return SystemViews.<ColocationColumnsWithTable>clusterViewBuilder() + .name("TABLES_COLOCATION_COLUMNS") + .addColumn("TABLE_NAME", STRING, entry -> entry.tableName) + .addColumn("COLOCATION_COLUMN", stringOf(SYSTEM_VIEW_STRING_COLUMN_LENGTH), entry -> entry.colocationColumn) + .dataProvider(viewDataPublisher) + .build(); + } + + private static class ColumnWithTableId { + private final CatalogTableColumnDescriptor descriptor; + private final String tableName; + private final String schema; + + private ColumnWithTableId(String schema, String tableName, CatalogTableColumnDescriptor descriptor) { + this.schema = schema; + this.tableName = tableName; + this.descriptor = descriptor; + } + } + + private static class ColocationColumnsWithTable { + private final String tableName; + private final String colocationColumn; + + private ColocationColumnsWithTable(String tableName, String colocationColumn) { + this.tableName = tableName; + this.colocationColumn = colocationColumn; + } + } + + private static class Info { + private final String name; + private final String schema; + private final int pkIndexId; + private final String zone; + + private Info(String name, String schema, int pkIndexId, String zone) { + this.name = name; + this.schema = schema; + this.pkIndexId = pkIndexId; + this.zone = zone; + } + } +} diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/ZonesSystemViewProvider.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/ZonesSystemViewProvider.java index 13be1e872e..c5579f2f47 100644 --- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/ZonesSystemViewProvider.java +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/systemviews/ZonesSystemViewProvider.java @@ -22,9 +22,11 @@ import static org.apache.ignite.internal.type.NativeTypes.INT32; import static org.apache.ignite.internal.type.NativeTypes.STRING; import java.util.List; +import java.util.Objects; import java.util.function.Supplier; import org.apache.ignite.internal.catalog.Catalog; import org.apache.ignite.internal.catalog.CatalogSystemViewProvider; +import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfileDescriptor; import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor; import org.apache.ignite.internal.systemview.api.SystemView; import org.apache.ignite.internal.systemview.api.SystemViews; @@ -43,7 +45,11 @@ public final class ZonesSystemViewProvider implements CatalogSystemViewProvider /** {@inheritDoc} */ @Override public List<SystemView<?>> getView(Supplier<Catalog> catalogSupplier) { - SystemView<?> zoneSystemView = SystemViews.<ZoneWithDefaultMarker>clusterViewBuilder() + return List.of(getZoneView(catalogSupplier), getStorageProfilesView(catalogSupplier)); + } + + private static SystemView<?> getZoneView(Supplier<Catalog> catalogSupplier) { + return SystemViews.<ZoneWithDefaultMarker>clusterViewBuilder() .name("ZONES") .addColumn("NAME", STRING, wrapper -> wrapper.zone.name()) .addColumn("PARTITIONS", INT32, wrapper -> wrapper.zone.partitions()) @@ -60,8 +66,34 @@ public final class ZonesSystemViewProvider implements CatalogSystemViewProvider } )) .build(); + } + + private static SystemView<?> getStorageProfilesView(Supplier<Catalog> catalogSupplier) { + Iterable<ZoneWithProfile> viewData = () -> { + Catalog catalog = catalogSupplier.get(); + + return catalog.zones().stream() + .flatMap(zone -> { + List<CatalogStorageProfileDescriptor> profiles = zone.storageProfiles().profiles(); + CatalogStorageProfileDescriptor defaultProfile = zone.storageProfiles().defaultProfile(); + + return profiles.stream().map(profile -> + new ZoneWithProfile( + zone.name(), + profile.storageProfile(), + Objects.equals(profile.storageProfile(), defaultProfile.storageProfile()) + ) + ); + }).iterator(); + }; - return List.of(zoneSystemView); + return SystemViews.<ZoneWithProfile>clusterViewBuilder() + .name("ZONE_STORAGE_PROFILES") + .addColumn("ZONE_NAME", STRING, zone -> zone.zoneName) + .addColumn("STORAGE_PROFILE", STRING, zone -> zone.profileName) + .addColumn("IS_DEFAULT_PROFILE", BOOLEAN, zone -> zone.isDefaultProfile) + .dataProvider(SubscriptionUtils.fromIterable(viewData)) + .build(); } /** Wraps a CatalogZoneDescriptor and a flag indicating whether this zone is the default zone. */ @@ -74,4 +106,19 @@ public final class ZonesSystemViewProvider implements CatalogSystemViewProvider this.isDefault = isDefault; } } + + /** + * Wraps a zone and a one of storage profile of the zone. + */ + private static class ZoneWithProfile { + private final String zoneName; + private final String profileName; + private final boolean isDefaultProfile; + + private ZoneWithProfile(String zoneName, String profileName, boolean defaultProfile) { + this.zoneName = zoneName; + this.profileName = profileName; + this.isDefaultProfile = defaultProfile; + } + } } diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java index 1ce5ce1845..92672382c3 100644 --- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java +++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java @@ -60,7 +60,7 @@ public class Main { AnsiConsole.systemInstall(); initReplExecutor(micronautFactory); initQuestionAsker(micronautFactory); - if (args.length != 0 || !isatty()) { // do not enter REPL if input or output is redirected + if (args.length != 0 /*|| !isatty()*/) { // do not enter REPL if input or output is redirected try { exitCode = executeCommand(args, micronautFactory); } catch (Exception e) { diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java b/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java index f43fcf4d16..5b3abbaa89 100644 --- a/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java +++ b/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java @@ -209,7 +209,7 @@ public class TcpIgniteClient implements IgniteClient { @Override public IgniteCatalog catalog() { - return new IgniteCatalogSqlImpl(sql(), tables); + return new IgniteCatalogSqlImpl(sql, tables); } /** {@inheritDoc} */ diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java index 92560a01b7..00d9793164 100644 --- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java +++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java @@ -99,7 +99,7 @@ import org.apache.ignite.internal.cluster.management.topology.api.LogicalTopolog import org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologyService; import org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot; import org.apache.ignite.internal.distributionzones.causalitydatanodes.CausalityDataNodesEngine; -import org.apache.ignite.internal.distributionzones.exception.DistributionZoneNotFoundException; +import org.apache.ignite.lang.DistributionZoneNotFoundException; import org.apache.ignite.internal.distributionzones.rebalance.DistributionZoneRebalanceEngine; import org.apache.ignite.internal.distributionzones.utils.CatalogAlterZoneEventListener; import org.apache.ignite.internal.lang.ByteArray; diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java index 838224f922..c61f6aa2ff 100644 --- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java +++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java @@ -52,7 +52,7 @@ import org.apache.ignite.internal.distributionzones.DistributionZoneManager.Zone import org.apache.ignite.internal.distributionzones.DistributionZonesUtil; import org.apache.ignite.internal.distributionzones.Node; import org.apache.ignite.internal.distributionzones.NodeWithAttributes; -import org.apache.ignite.internal.distributionzones.exception.DistributionZoneNotFoundException; +import org.apache.ignite.lang.DistributionZoneNotFoundException; import org.apache.ignite.internal.lang.ByteArray; import org.apache.ignite.internal.metastorage.Entry; import org.apache.ignite.internal.metastorage.MetaStorageManager; diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java index 63c0c5b882..71309e15e2 100644 --- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java +++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java @@ -73,7 +73,7 @@ import org.apache.ignite.internal.distributionzones.DistributionZoneManager; import org.apache.ignite.internal.distributionzones.DistributionZonesUtil; import org.apache.ignite.internal.distributionzones.Node; import org.apache.ignite.internal.distributionzones.NodeWithAttributes; -import org.apache.ignite.internal.distributionzones.exception.DistributionZoneNotFoundException; +import org.apache.ignite.lang.DistributionZoneNotFoundException; import org.apache.ignite.internal.distributionzones.utils.CatalogAlterZoneEventListener; import org.apache.ignite.internal.lang.IgniteBiTuple; import org.apache.ignite.internal.manager.ComponentContext; diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/threading/PublicApiThreadingIgniteCatalog.java b/modules/runner/src/main/java/org/apache/ignite/internal/threading/PublicApiThreadingIgniteCatalog.java index 0316465336..db1c0e8de6 100644 --- a/modules/runner/src/main/java/org/apache/ignite/internal/threading/PublicApiThreadingIgniteCatalog.java +++ b/modules/runner/src/main/java/org/apache/ignite/internal/threading/PublicApiThreadingIgniteCatalog.java @@ -78,6 +78,16 @@ public class PublicApiThreadingIgniteCatalog implements IgniteCatalog, Wrapper { return wrapTableForPublicUse(table); } + @Override + public CompletableFuture<TableDefinition> tableDefinitionAsync(String tableName) { + return doAsyncOperation(() -> catalog.tableDefinitionAsync(tableName)); + } + + @Override + public TableDefinition tableDefinition(String tableName) { + return execUserSyncOperation(() -> catalog.tableDefinition(tableName)); + } + @Override public CompletableFuture<Void> createZoneAsync(ZoneDefinition definition) { return doAsyncOperation(() -> catalog.createZoneAsync(definition)); @@ -88,6 +98,17 @@ public class PublicApiThreadingIgniteCatalog implements IgniteCatalog, Wrapper { execUserSyncOperation(() -> catalog.createZone(definition)); } + + @Override + public CompletableFuture<ZoneDefinition> zoneDefinitionAsync(String zoneName) { + return execUserSyncOperation(() -> catalog.zoneDefinitionAsync(zoneName)); + } + + @Override + public ZoneDefinition zoneDefinition(String zoneName) { + return execUserSyncOperation(() -> catalog.zoneDefinition(zoneName)); + } + @Override public CompletableFuture<Void> dropTableAsync(TableDefinition definition) { return doAsyncOperation(() -> catalog.dropTableAsync(definition)); diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryManager.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryManager.java index 83899f4e40..c25ae87e82 100644 --- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryManager.java +++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryManager.java @@ -59,7 +59,7 @@ import org.apache.ignite.internal.catalog.events.CreateTableEventParameters; import org.apache.ignite.internal.catalog.events.DropTableEventParameters; import org.apache.ignite.internal.distributionzones.DistributionZoneManager; import org.apache.ignite.internal.distributionzones.NodeWithAttributes; -import org.apache.ignite.internal.distributionzones.exception.DistributionZoneNotFoundException; +import org.apache.ignite.lang.DistributionZoneNotFoundException; import org.apache.ignite.internal.lang.ByteArray; import org.apache.ignite.internal.lang.NodeStoppingException; import org.apache.ignite.internal.logger.IgniteLogger;
