This is an automated email from the ASF dual-hosted git repository.
zstan 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 48505b660b IGNITE-20634 Sql. Indices with write-only status should not
be accessible via sql schemas. (#2712)
48505b660b is described below
commit 48505b660b2ec2e50c9ed9f408b6abbebbfb9555
Author: Max Zhuravkov <[email protected]>
AuthorDate: Wed Nov 22 07:20:51 2023 +0200
IGNITE-20634 Sql. Indices with write-only status should not be accessible
via sql schemas. (#2712)
---
modules/runner/build.gradle | 1 +
.../internal/sql/BaseSqlIntegrationTest.java | 2 +-
.../ignite/internal/sql/api/ItSqlApiBaseTest.java | 3 +
.../internal/sql/engine/ItAggregatesTest.java | 3 -
.../sql/engine/ItBuildIndexOneNodeTest.java | 6 ++
.../internal/sql/engine/ItBuildIndexTest.java | 32 ++++++
.../internal/sql/engine/ItIndexSpoolTest.java | 5 +-
.../ignite/internal/sql/engine/ItJoinTest.java | 2 +-
.../internal/ClusterPerClassIntegrationTest.java | 106 +++++++++++++++++-
.../sql/engine/schema/SqlSchemaManagerImpl.java | 4 +
.../sql/engine/framework/TestBuilders.java | 52 +++++++--
.../engine/schema/SqlSchemaManagerImplTest.java | 118 ++++++++++++++++-----
12 files changed, 295 insertions(+), 39 deletions(-)
diff --git a/modules/runner/build.gradle b/modules/runner/build.gradle
index 7140543f41..ed44e9e90e 100644
--- a/modules/runner/build.gradle
+++ b/modules/runner/build.gradle
@@ -194,6 +194,7 @@ dependencies {
testFixturesImplementation testFixtures(project(':ignite-core'))
testFixturesImplementation testFixtures(project(':ignite-sql-engine'))
testFixturesImplementation testFixtures(project(':ignite-network'))
+ testFixturesImplementation testFixtures(project(':ignite-catalog'))
testFixturesImplementation libs.jetbrains.annotations
testFixturesImplementation libs.hamcrest.core
testFixturesImplementation libs.auto.service.annotations
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/BaseSqlIntegrationTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/BaseSqlIntegrationTest.java
index 08159d7567..49d96eeca2 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/BaseSqlIntegrationTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/BaseSqlIntegrationTest.java
@@ -256,7 +256,7 @@ public class BaseSqlIntegrationTest extends
ClusterPerClassIntegrationTest {
* @return Nodes on which the partition index was built.
* @throws Exception If failed.
*/
- protected static Map<Integer, List<Ignite>> waitForIndexBuild(String
tableName, String indexName) throws Exception {
+ protected static Map<Integer, List<Ignite>> waitForIndexBuild(String
tableName, String indexName) {
Map<Integer, List<Ignite>> partitionIdToNodes = new HashMap<>();
CLUSTER.runningNodes().forEach(clusterNode -> {
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
index 1e9eace154..ba287ca8de 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
@@ -83,6 +83,9 @@ public abstract class ItSqlApiBaseTest extends
BaseSqlIntegrationTest {
@Test
public void ddl() throws Exception {
+ // Do not wait for indexes to become available.
+ setAwaitIndexAvailability(false);
+
IgniteSql sql = igniteSql();
Session ses = sql.createSession();
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
index fb4df325f1..42510495ba 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
@@ -65,9 +65,6 @@ public class ItAggregatesTest extends BaseSqlIntegrationTest {
sql("CREATE TABLE test (id INT PRIMARY KEY, grp0 INT, grp1 INT, val0
INT, val1 INT) WITH PRIMARY_ZONE='TEST_ZONE'");
sql("CREATE TABLE test_one_col_idx (pk INT PRIMARY KEY, col0 INT)");
- sql("CREATE INDEX test_idx ON test(grp0, grp1)");
- sql("CREATE INDEX test_one_col_idx_idx ON test_one_col_idx(col0)");
-
for (int i = 0; i < ROWS; i++) {
sql("INSERT INTO test (id, grp0, grp1, val0, val1) VALUES (?, ?,
?, ?, ?)", i, i / 10, i / 100, 1, 2);
sql("INSERT INTO test_one_col_idx (pk, col0) VALUES (?, ?)", i, i);
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexOneNodeTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexOneNodeTest.java
index 8d6cf2cc9a..8941337b4b 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexOneNodeTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexOneNodeTest.java
@@ -31,6 +31,7 @@ import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
import
org.apache.ignite.internal.table.distributed.replication.request.BuildIndexReplicaRequest;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Integration test for testing the building of an index in a single node
cluster. */
@@ -46,6 +47,11 @@ public class ItBuildIndexOneNodeTest extends
BaseSqlIntegrationTest {
return 1;
}
+ @BeforeEach
+ void setup() {
+ setAwaitIndexAvailability(false);
+ }
+
@AfterEach
void tearDown() {
sql("DROP TABLE IF EXISTS " + TABLE_NAME);
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexTest.java
index e3366fc3eb..1c7d913e19 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItBuildIndexTest.java
@@ -39,7 +39,9 @@ import java.util.function.BiPredicate;
import java.util.stream.Stream;
import org.apache.ignite.Ignite;
import org.apache.ignite.internal.app.IgniteImpl;
+import org.apache.ignite.internal.catalog.CatalogManager;
import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.lang.IgniteStringFormatter;
import org.apache.ignite.internal.raft.Command;
import org.apache.ignite.internal.raft.Peer;
@@ -54,6 +56,7 @@ import org.apache.ignite.raft.jraft.rpc.WriteActionRequest;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -67,6 +70,12 @@ public class ItBuildIndexTest extends BaseSqlIntegrationTest
{
private static final String INDEX_NAME = "TEST_INDEX";
+ @BeforeEach
+ void setup() {
+ // Do not wait for indexes to become available.
+ setAwaitIndexAvailability(false);
+ }
+
@AfterEach
void tearDown() {
sql("DROP TABLE IF EXISTS " + TABLE_NAME);
@@ -275,6 +284,10 @@ public class ItBuildIndexTest extends
BaseSqlIntegrationTest {
IgniteStringFormatter.format("p={}, nodes={}",
entry.getKey(), entry.getValue())
);
}
+
+ assertTrue(waitForCondition(() -> isIndexAvailable(INDEX_NAME),
10_000));
+
+ waitForReadTimestampThatObservesMostRecentCatalog();
}
/**
@@ -288,4 +301,23 @@ public class ItBuildIndexTest extends
BaseSqlIntegrationTest {
return indexDescriptor == null ? null : indexDescriptor.id();
}
+
+ /**
+ * Returns {@code true} if index with the given name is available.
+ *
+ * @param indexName Index nane.
+ * @return True if index is available or false if index does not exist or
is not available.
+ */
+ private static boolean isIndexAvailable(String indexName) {
+ IgniteImpl ignite = CLUSTER.runningNodes()
+ .findAny()
+ .orElseThrow(() -> new IllegalStateException("No running
nodes"));
+
+ CatalogManager catalogManager = ignite.catalogManager();
+ HybridClock clock = ignite.clock();
+
+ CatalogIndexDescriptor indexDescriptor =
catalogManager.index(indexName, clock.nowLong());
+
+ return indexDescriptor != null && indexDescriptor.available();
+ }
}
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
index 93233f9602..dd4b3e3432 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
@@ -26,6 +26,7 @@ import java.util.stream.Stream;
import org.apache.ignite.internal.ClusterPerClassIntegrationTest;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
+import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
import org.apache.ignite.table.Table;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.params.ParameterizedTest;
@@ -35,7 +36,7 @@ import org.junit.jupiter.params.provider.MethodSource;
/**
* Index spool test.
*/
-public class ItIndexSpoolTest extends ClusterPerClassIntegrationTest {
+public class ItIndexSpoolTest extends BaseSqlIntegrationTest {
private static final IgniteLogger LOG =
Loggers.forClass(ClusterPerClassIntegrationTest.class);
/**
@@ -86,7 +87,7 @@ public class ItIndexSpoolTest extends
ClusterPerClassIntegrationTest {
res.forEach(r -> assertThat(r.get(0), is(r.get(1))));
}
- private void prepareDataSet(int rowsCount, int parts) throws
InterruptedException {
+ private void prepareDataSet(int rowsCount, int parts) {
Object[][] dataRows = new Object[rowsCount][];
for (int i = 0; i < rowsCount; i++) {
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItJoinTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItJoinTest.java
index 7ea2a07aac..183e62d243 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItJoinTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItJoinTest.java
@@ -791,7 +791,7 @@ public class ItJoinTest extends BaseSqlIntegrationTest {
@ParameterizedTest(name = "join algo : {0}, index present: {1}")
@MethodSource("joinTypes")
@WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
- public void testIsNotDistinctFrom(JoinType joinType, boolean indexScan)
throws InterruptedException {
+ public void testIsNotDistinctFrom(JoinType joinType, boolean indexScan) {
try {
sql("CREATE TABLE t11(i1 INTEGER, i2 INTEGER)");
diff --git
a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
index 6e7ea31302..6f4fb844b9 100644
---
a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
+++
b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
@@ -18,19 +18,33 @@
package org.apache.ignite.internal;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static
org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.ignite.internal.app.IgniteImpl;
+import org.apache.ignite.internal.catalog.CatalogManager;
+import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogObjectDescriptor;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.sql.engine.util.SqlTestUtils;
+import org.apache.ignite.internal.testframework.TestIgnitionManager;
import org.apache.ignite.internal.testframework.WorkDirectory;
import org.apache.ignite.table.Table;
import org.apache.ignite.tx.Transaction;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.TestInstance;
@@ -57,10 +71,22 @@ public abstract class ClusterPerClassIntegrationTest
extends IgniteIntegrationTe
/** Cluster nodes. */
protected static Cluster CLUSTER;
+ private static final boolean DEFAULT_WAIT_FOR_INDEX_AVAILABLE = true;
+
+ /** Whether to wait for indexes to become available or not. Default is
{@code true}. */
+ private static final AtomicBoolean AWAIT_INDEX_AVAILABILITY = new
AtomicBoolean(DEFAULT_WAIT_FOR_INDEX_AVAILABLE);
+
/** Work directory. */
@WorkDirectory
private static Path WORK_DIR;
+ /** Reset {@link #AWAIT_INDEX_AVAILABILITY}. */
+ @BeforeEach
+ @AfterEach
+ void resetIndexAvailabilityFlag() {
+ setAwaitIndexAvailability(DEFAULT_WAIT_FOR_INDEX_AVAILABLE);
+ }
+
/**
* Before all.
*
@@ -170,6 +196,15 @@ public abstract class ClusterPerClassIntegrationTest
extends IgniteIntegrationTe
sql(format("CREATE INDEX {} ON {} ({})", indexName, tableName,
columnName));
}
+ /**
+ * Sets whether to wait for indexes to become available.
+ *
+ * @param value Whether to wait for indexes to become available.
+ */
+ protected static void setAwaitIndexAvailability(boolean value) {
+ AWAIT_INDEX_AVAILABILITY.set(value);
+ }
+
protected static void insertData(String tblName, List<String> columnNames,
Object[]... tuples) {
Transaction tx = CLUSTER.node(0).transactions().begin();
@@ -192,7 +227,12 @@ public abstract class ClusterPerClassIntegrationTest
extends IgniteIntegrationTe
}
protected static List<List<Object>> sql(@Nullable Transaction tx, String
sql, Object... args) {
- return SqlTestUtils.sql(CLUSTER.node(0), tx, sql, args);
+ IgniteImpl node = CLUSTER.node(0);
+ if (!AWAIT_INDEX_AVAILABILITY.get()) {
+ return SqlTestUtils.sql(node, tx, sql, args);
+ } else {
+ return executeAwaitingIndexes(node, (n) -> SqlTestUtils.sql(n, tx,
sql, args));
+ }
}
/**
@@ -227,4 +267,68 @@ public abstract class ClusterPerClassIntegrationTest
extends IgniteIntegrationTe
this.salary = salary;
}
}
+
+ /**
+ * Waits for some amount of time so that read-only transactions can
observe the most recent version of the catalog.
+ */
+ protected static void waitForReadTimestampThatObservesMostRecentCatalog()
{
+ // See TxManagerImpl::currentReadTimestamp.
+ long delay = HybridTimestamp.CLOCK_SKEW +
TestIgnitionManager.DEFAULT_PARTITION_IDLE_SYNC_TIME_INTERVAL_MS;
+ try {
+ TimeUnit.MILLISECONDS.sleep(delay);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static List<List<Object>> executeAwaitingIndexes(IgniteImpl node,
Function<IgniteImpl, List<List<Object>>> statement) {
+ CatalogManager catalogManager = node.catalogManager();
+
+ // Get existing indexes
+ Set<Integer> existing =
catalogManager.indexes(catalogManager.latestCatalogVersion())
+ .stream().map(CatalogObjectDescriptor::id)
+ .collect(Collectors.toSet());
+
+ List<List<Object>> result = statement.apply(node);
+
+ // Get indexes after a statement and compute the difference
+ Set<Integer> difference =
catalogManager.indexes(catalogManager.latestCatalogVersion()).stream()
+ .map(CatalogObjectDescriptor::id)
+ .collect(Collectors.toSet());
+
+ difference.removeAll(existing);
+
+ if (difference.isEmpty()) {
+ return result;
+ }
+
+ // If there are new indexes, wait for them to become available.
+
+ try {
+ assertTrue(waitForCondition(() -> {
+ int latestVersion = catalogManager.latestCatalogVersion();
+ int notAvailable = 0;
+
+ for (CatalogIndexDescriptor index :
catalogManager.indexes(latestVersion)) {
+ if (!index.available() && difference.contains(index.id()))
{
+ notAvailable++;
+ }
+ }
+
+ return notAvailable == 0;
+ }, 10_000));
+
+ // We have no knowledge whether the next transaction is readonly
or not,
+ // so we have to assume that the next transaction is read only
transaction.
+ // otherwise the statements in that transaction may not observe
+ // the latest catalog version.
+ waitForReadTimestampThatObservesMostRecentCatalog();
+
+ return result;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+
+ throw new IllegalStateException(e);
+ }
+ }
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
index 5c6ac58a02..b6889d32ed 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
@@ -177,6 +177,10 @@ public class SqlSchemaManagerImpl implements
SqlSchemaManager {
// Assemble indexes as they are required by tables.
for (CatalogIndexDescriptor indexDescriptor :
schemaDescriptor.indexes()) {
+ if (!indexDescriptor.available()) {
+ continue;
+ }
+
int tableId = indexDescriptor.tableId();
TableDescriptor tableDescriptor = tableDescriptorMap.get(tableId);
assert tableDescriptor != null : "Table is not found in schema: "
+ tableId;
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 200db05a0f..2f73c043c0 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
@@ -38,7 +38,9 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Flow.Publisher;
import java.util.function.Function;
import java.util.stream.Collectors;
+import org.apache.ignite.internal.catalog.Catalog;
import org.apache.ignite.internal.catalog.CatalogCommand;
+import org.apache.ignite.internal.catalog.CatalogManager;
import org.apache.ignite.internal.catalog.CatalogManagerImpl;
import org.apache.ignite.internal.catalog.CatalogTestUtils;
import org.apache.ignite.internal.catalog.commands.ColumnParams;
@@ -47,7 +49,10 @@ import
org.apache.ignite.internal.catalog.commands.CreateHashIndexCommand;
import org.apache.ignite.internal.catalog.commands.CreateSortedIndexCommand;
import org.apache.ignite.internal.catalog.commands.CreateTableCommand;
import org.apache.ignite.internal.catalog.commands.DefaultValue;
+import org.apache.ignite.internal.catalog.commands.MakeIndexAvailableCommand;
import org.apache.ignite.internal.catalog.descriptors.CatalogColumnCollation;
+import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
import
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
import org.apache.ignite.internal.hlc.HybridClockImpl;
@@ -542,11 +547,7 @@ public class TestBuilders {
}
}
- List<CatalogCommand> initialSchema = tableBuilders.stream()
- .flatMap(builder -> builder.build().stream())
- .collect(Collectors.toList());
-
- Runnable initClosure = () ->
await(catalogManager.execute(initialSchema));
+ Runnable initClosure = () -> initAction(catalogManager);
var ddlHandler = new DdlCommandHandler(catalogManager);
var schemaManager = new SqlSchemaManagerImpl(catalogManager,
CaffeineCacheFactory.INSTANCE, 0);
@@ -624,6 +625,41 @@ public class TestBuilders {
+ "[{}]", problematicTablesString));
}
}
+
+ private void initAction(CatalogManager catalogManager) {
+ List<CatalogCommand> initialSchema = tableBuilders.stream()
+ .flatMap(builder -> builder.build().stream())
+ .collect(Collectors.toList());
+
+ // Init schema
+ await(catalogManager.execute(initialSchema));
+
+ // Make indexes available
+ List<CatalogCommand> makeIndexesAvailable = new ArrayList<>();
+
+ Catalog catalog =
catalogManager.catalog(catalogManager.latestCatalogVersion());
+
+ for (ClusterTableBuilderImpl tableBuilder : tableBuilders) {
+ String schemaName = tableBuilder.schemaName;
+ CatalogSchemaDescriptor schema = catalog.schema(schemaName);
+ assert schema != null : "SchemaDescriptor does not exist: " +
schemaName;
+
+ for (AbstractClusterTableIndexBuilderImpl<?> indexBuilder :
tableBuilder.indexBuilders) {
+ String indexName = indexBuilder.name;
+ CatalogIndexDescriptor index =
Arrays.stream(schema.indexes())
+ .filter(idx -> idx.name().equals(indexName))
+ .findAny()
+ .orElseThrow(() -> new
AssertionError("IndexDescriptor does not exist: " + indexName));
+
+ CatalogCommand command =
MakeIndexAvailableCommand.builder()
+ .indexId(index.id())
+ .build();
+ makeIndexesAvailable.add(command);
+ }
+ }
+
+ await(catalogManager.execute(makeIndexesAvailable));
+ }
}
private static class TableBuilderImpl implements TableBuilder {
@@ -759,6 +795,8 @@ public class TestBuilders {
private final ClusterBuilderImpl parent;
+ private final String schemaName = CatalogManager.DEFAULT_SCHEMA_NAME;
+
private String name;
private ClusterTableBuilderImpl(ClusterBuilderImpl parent) {
@@ -825,7 +863,7 @@ public class TestBuilders {
commands.add(
CreateTableCommand.builder()
- .schemaName("PUBLIC")
+ .schemaName(schemaName)
.tableName(name)
.columns(columns)
.primaryKeyColumns(keyColumns)
@@ -833,7 +871,7 @@ public class TestBuilders {
);
for (AbstractClusterTableIndexBuilderImpl<?> builder :
indexBuilders) {
- commands.add(builder.build("PUBLIC", name));
+ commands.add(builder.build(schemaName, name));
}
return commands;
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
index 10078b4e99..24f5ab8037 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
@@ -34,7 +34,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.function.Function;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelFieldCollation;
@@ -52,7 +54,9 @@ import
org.apache.ignite.internal.catalog.commands.CreateSystemViewCommand;
import org.apache.ignite.internal.catalog.commands.CreateTableCommand;
import org.apache.ignite.internal.catalog.commands.CreateTableCommandBuilder;
import org.apache.ignite.internal.catalog.commands.DefaultValue;
+import org.apache.ignite.internal.catalog.commands.MakeIndexAvailableCommand;
import org.apache.ignite.internal.catalog.descriptors.CatalogColumnCollation;
+import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
import
org.apache.ignite.internal.catalog.descriptors.CatalogSystemViewDescriptor;
import
org.apache.ignite.internal.catalog.descriptors.CatalogSystemViewDescriptor.SystemViewType;
@@ -67,6 +71,7 @@ import
org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
import org.apache.ignite.internal.sql.engine.util.cache.CaffeineCacheFactory;
import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
import org.apache.ignite.sql.ColumnType;
+import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -403,25 +408,41 @@ public class SqlSchemaManagerImplTest extends
BaseIgniteAbstractTest {
createHashIndex("T1", "VAL1_IDX", "VAL1")
)));
- int versionAfter = catalogManager.latestCatalogVersion();
- assertThat(versionAfter, equalTo(versionBefore + 1));
+ {
+ int versionAfter = catalogManager.latestCatalogVersion();
+ assertThat(versionAfter, equalTo(versionBefore + 1));
- SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
- assertNotNull(rootSchema);
+ SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
+ assertNotNull(rootSchema);
- SchemaPlus schemaPlus = rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
- assertNotNull(schemaPlus);
+ SchemaPlus schemaPlus =
rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
+ assertNotNull(schemaPlus);
- IgniteTable table = getTable(unwrapSchema(schemaPlus), "T1");
- assertNotNull(table);
+ IgniteIndex index = findIndex(unwrapSchema(schemaPlus), "T1",
"VAL1_IDX");
+ assertNull(index, "Index should not be available");
+ }
- IgniteIndex index = table.indexes().get("VAL1_IDX");
+ makeIndexAvailable("VAL1_IDX");
- assertThat(index.name(), equalTo("VAL1_IDX"));
- assertThat(index.type(), equalTo(Type.HASH));
- assertThat(index.collation(), equalTo(RelCollations.of(
- new RelFieldCollation(1, Direction.CLUSTERED,
NullDirection.UNSPECIFIED)
- )));
+ {
+ int versionAfter = catalogManager.latestCatalogVersion();
+ assertThat(versionAfter, equalTo(versionBefore + 2));
+
+ SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
+ assertNotNull(rootSchema);
+
+ SchemaPlus schemaPlus =
rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
+ assertNotNull(schemaPlus);
+
+ IgniteIndex index = findIndex(unwrapSchema(schemaPlus), "T1",
"VAL1_IDX");
+ assertNotNull(index);
+
+ assertThat(index.name(), equalTo("VAL1_IDX"));
+ assertThat(index.type(), equalTo(Type.HASH));
+ assertThat(index.collation(), equalTo(RelCollations.of(
+ new RelFieldCollation(1, Direction.CLUSTERED,
NullDirection.UNSPECIFIED)
+ )));
+ }
}
@Test
@@ -435,20 +456,37 @@ public class SqlSchemaManagerImplTest extends
BaseIgniteAbstractTest {
List.of(CatalogColumnCollation.DESC_NULLS_FIRST,
CatalogColumnCollation.DESC_NULLS_LAST))
)));
- int versionAfter = catalogManager.latestCatalogVersion();
- assertThat(versionAfter, equalTo(versionBefore + 1));
+ {
+ int versionAfter = catalogManager.latestCatalogVersion();
+ assertThat(versionAfter, equalTo(versionBefore + 1));
- SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
- assertNotNull(rootSchema);
+ SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
+ assertNotNull(rootSchema);
- SchemaPlus schemaPlus = rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
- assertNotNull(schemaPlus);
+ SchemaPlus schemaPlus =
rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
+ assertNotNull(schemaPlus);
- IgniteTable table = getTable(unwrapSchema(schemaPlus), "T1");
- assertNotNull(table);
+ IgniteIndex index1 = findIndex(unwrapSchema(schemaPlus), "T1",
"IDX1");
+ assertNull(index1);
+
+ IgniteIndex index2 = findIndex(unwrapSchema(schemaPlus), "T1",
"IDX2");
+ assertNull(index2);
+ }
+
+ makeIndexAvailable("IDX1");
{
- IgniteIndex index = table.indexes().get("IDX1");
+ int versionAfter = catalogManager.latestCatalogVersion();
+ assertThat(versionAfter, equalTo(versionBefore + 2));
+
+ SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
+ assertNotNull(rootSchema);
+
+ SchemaPlus schemaPlus =
rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
+ assertNotNull(schemaPlus);
+
+ IgniteIndex index = findIndex(unwrapSchema(schemaPlus), "T1",
"IDX1");
+ assertNotNull(index);
assertThat(index.name(), equalTo("IDX1"));
assertThat(index.type(), equalTo(Type.SORTED));
@@ -458,8 +496,20 @@ public class SqlSchemaManagerImplTest extends
BaseIgniteAbstractTest {
)));
}
+ makeIndexAvailable("IDX2");
+
{
- IgniteIndex index = table.indexes().get("IDX2");
+ int versionAfter = catalogManager.latestCatalogVersion();
+ assertThat(versionAfter, equalTo(versionBefore + 3));
+
+ SchemaPlus rootSchema = sqlSchemaManager.schema(versionAfter);
+ assertNotNull(rootSchema);
+
+ SchemaPlus schemaPlus =
rootSchema.getSubSchema(PUBLIC_SCHEMA_NAME);
+ assertNotNull(schemaPlus);
+
+ IgniteIndex index = findIndex(unwrapSchema(schemaPlus), "T1",
"IDX2");
+ assertNotNull(index);
assertThat(index.name(), equalTo("IDX2"));
assertThat(index.type(), equalTo(Type.SORTED));
@@ -470,6 +520,20 @@ public class SqlSchemaManagerImplTest extends
BaseIgniteAbstractTest {
}
}
+ private void makeIndexAvailable(String name) {
+ Map<String, CatalogIndexDescriptor> indices =
catalogManager.indexes(catalogManager.latestCatalogVersion())
+
.stream().collect(Collectors.toMap(CatalogIndexDescriptor::name,
Function.identity()));
+
+ CatalogIndexDescriptor indexDescriptor = indices.get(name);
+ assertNotNull(indexDescriptor, indices.toString());
+
+ CatalogCommand makeAvailable = MakeIndexAvailableCommand.builder()
+ .indexId(indexDescriptor.id())
+ .build();
+
+ await(catalogManager.execute(List.of(makeAvailable)));
+ }
+
@ParameterizedTest
@MethodSource("systemViewDistributions")
public void testBasicView(SystemViewType viewType, IgniteDistribution
distribution) {
@@ -596,6 +660,12 @@ public class SqlSchemaManagerImplTest extends
BaseIgniteAbstractTest {
return table;
}
+ private static @Nullable IgniteIndex findIndex(IgniteSchema schema, String
tableName, String indexName) {
+ IgniteTable table = (IgniteTable) schema.getTable(tableName);
+ assertNotNull(table);
+ return table.indexes().get(indexName);
+ }
+
private static Stream<Arguments> columnTypes() {
return Stream.of(
Arguments.of(ColumnType.BOOLEAN, -1, -1),