/* * 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.processors.cache.index; import org.apache.ignite.Ignite; import org.apache.ignite.Ignition; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.QueryIndex; import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.schema.SchemaOperationException; import org.apache.ignite.internal.util.GridStringBuilder; import org.apache.ignite.internal.util.typedef.internal.SB; import javax.cache.CacheException; import java.util.Arrays; import java.util.List; import java.util.Map; import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC; import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; import static org.apache.ignite.cache.CacheMode.LOCAL; import static org.apache.ignite.cache.CacheMode.PARTITIONED; import static org.apache.ignite.cache.CacheMode.REPLICATED; /** * Tests for dynamic index creation. */ @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbstractSelfTest { /** Node index for regular server (coordinator). */ protected static final int IDX_SRV_CRD = 0; /** Node index for regular server (not coordinator). */ protected static final int IDX_SRV_NON_CRD = 1; /** Node index for regular client. */ protected static final int IDX_CLI = 2; /** Node index for server which doesn't pass node filter. */ protected static final int IDX_SRV_FILTERED = 3; /** Node index for client with near-only cache. */ protected static final int IDX_CLI_NEAR_ONLY = 4; /** {@inheritDoc} */ @Override protected void beforeTestsStarted() throws Exception { super.beforeTestsStarted(); for (IgniteConfiguration cfg : configurations()) Ignition.start(cfg); } /** {@inheritDoc} */ @Override protected void afterTest() throws Exception { node().destroyCache(CACHE_NAME); super.afterTest(); } /** * Initialize cache for tests. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. */ private void initialize(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) { node().getOrCreateCache(cacheConfiguration(mode, atomicityMode, near)); grid(IDX_CLI_NEAR_ONLY).getOrCreateNearCache(CACHE_NAME, new NearCacheConfiguration<>()); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); loadInitialData(); } /** * Create cache with the given cache mode and atomicity mode. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Whether near cache should be initialized. * @return Cache configuration. */ private CacheConfiguration<KeyClass, ValueClass> cacheConfiguration(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) { CacheConfiguration<KeyClass, ValueClass> ccfg = cacheConfiguration(); ccfg.setCacheMode(mode); ccfg.setAtomicityMode(atomicityMode); if (near) ccfg.setNearConfiguration(new NearCacheConfiguration<KeyClass, ValueClass>()); return ccfg; } /** * Load initial data. */ private void loadInitialData() { put(node(), 0, KEY_BEFORE); } /** * Test simple index create for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testCreatePartitionedAtomic() throws Exception { checkCreate(PARTITIONED, ATOMIC, false); } /** * Test simple index create for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testCreatePartitionedAtomicNear() throws Exception { checkCreate(PARTITIONED, ATOMIC, true); } /** * Test simple index create for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreatePartitionedTransactional() throws Exception { checkCreate(PARTITIONED, TRANSACTIONAL, false); } /** * Test simple index create for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testCreatePartitionedTransactionalNear() throws Exception { checkCreate(PARTITIONED, TRANSACTIONAL, true); } /** * Test simple index create for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateReplicatedAtomic() throws Exception { checkCreate(REPLICATED, ATOMIC, false); } /** * Test simple index create for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateReplicatedTransactional() throws Exception { checkCreate(REPLICATED, TRANSACTIONAL, false); } /** * Check normal create operation. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkCreate(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1)); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false); assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1)); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false); } }, IgniteQueryErrorCode.INDEX_ALREADY_EXISTS); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, true); assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1)); assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1); assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1); } /** * Test composite index creation for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateCompositePartitionedAtomic() throws Exception { checkCreateComposite(PARTITIONED, ATOMIC, false); } /** * Test composite index creation for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testCreateCompositePartitionedAtomicNear() throws Exception { checkCreateComposite(PARTITIONED, ATOMIC, true); } /** * Test composite index creation for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateCompositePartitionedTransactional() throws Exception { checkCreateComposite(PARTITIONED, TRANSACTIONAL, false); } /** * Test composite index creation for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testCreateCompositePartitionedTransactionalNear() throws Exception { checkCreateComposite(PARTITIONED, TRANSACTIONAL, true); } /** * Test composite index creation for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateCompositeReplicatedAtomic() throws Exception { checkCreateComposite(REPLICATED, ATOMIC, false); } /** * Test composite index creation for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateCompositeReplicatedTransactional() throws Exception { checkCreateComposite(REPLICATED, TRANSACTIONAL, false); } /** * Check composite index creation. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkCreateComposite(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1), field(alias(FIELD_NAME_2))); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false); assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1), field(alias(FIELD_NAME_2))); assertCompositeIndexOperations(SQL_COMPOSITE); assertIndexUsed(IDX_NAME_1, SQL_COMPOSITE, SQL_ARG_1, SQL_ARG_2); } /** * Test create when cache doesn't exist for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateNoCachePartitionedAtomic() throws Exception { checkCreateNotCache(PARTITIONED, ATOMIC, false); } /** * Test create when cache doesn't exist for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testCreateNoCachePartitionedAtomicNear() throws Exception { checkCreateNotCache(PARTITIONED, ATOMIC, true); } /** * Test create when cache doesn't exist for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateNoCachePartitionedTransactional() throws Exception { checkCreateNotCache(PARTITIONED, TRANSACTIONAL, false); } /** * Test create when cache doesn't exist for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testCreateNoCachePartitionedTransactionalNear() throws Exception { checkCreateNotCache(PARTITIONED, TRANSACTIONAL, true); } /** * Test create when cache doesn't exist for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateNoCacheReplicatedAtomic() throws Exception { checkCreateNotCache(REPLICATED, ATOMIC, false); } /** * Test create when cache doesn't exist for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateNoCacheReplicatedTransactional() throws Exception { checkCreateNotCache(REPLICATED, TRANSACTIONAL, false); } /** * Check create when cache doesn't exist. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkCreateNotCache(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1)); try { queryProcessor(node()).dynamicIndexCreate(randomString(), TBL_NAME, idx, false).get(); } catch (SchemaOperationException e) { assertEquals(SchemaOperationException.CODE_CACHE_NOT_FOUND, e.code()); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); return; } catch (Exception e) { fail("Unexpected exception: " + e); } fail(SchemaOperationException.class.getSimpleName() + " is not thrown."); } /** * Test create when table doesn't exist for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateNoTablePartitionedAtomic() throws Exception { checkCreateNoTable(PARTITIONED, ATOMIC, false); } /** * Test create when table doesn't exist for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testCreateNoTablePartitionedAtomicNear() throws Exception { checkCreateNoTable(PARTITIONED, ATOMIC, true); } /** * Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateNoTablePartitionedTransactional() throws Exception { checkCreateNoTable(PARTITIONED, TRANSACTIONAL, false); } /** * Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testCreateNoTablePartitionedTransactionalNear() throws Exception { checkCreateNoTable(PARTITIONED, TRANSACTIONAL, true); } /** * Test create when table doesn't exist for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateNoTableReplicatedAtomic() throws Exception { checkCreateNoTable(REPLICATED, ATOMIC, false); } /** * Test create when table doesn't exist for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateNoTableReplicatedTransactional() throws Exception { checkCreateNoTable(REPLICATED, TRANSACTIONAL, false); } /** * Check create when table doesn't exist. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkCreateNoTable(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1)); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { dynamicIndexCreate(CACHE_NAME, randomString(), idx, false); } }, IgniteQueryErrorCode.TABLE_NOT_FOUND); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); } /** * Test create when table doesn't exist for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateNoColumnPartitionedAtomic() throws Exception { checkCreateNoColumn(PARTITIONED, ATOMIC, false); } /** * Test create when table doesn't exist for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testCreateNoColumnPartitionedAtomicNear() throws Exception { checkCreateNoColumn(PARTITIONED, ATOMIC, true); } /** * Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateNoColumnPartitionedTransactional() throws Exception { checkCreateNoColumn(PARTITIONED, TRANSACTIONAL, false); } /** * Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testCreateNoColumnPartitionedTransactionalNear() throws Exception { checkCreateNoColumn(PARTITIONED, TRANSACTIONAL, true); } /** * Test create when table doesn't exist for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateNoColumnReplicatedAtomic() throws Exception { checkCreateNoColumn(REPLICATED, ATOMIC, false); } /** * Test create when table doesn't exist for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateNoColumnReplicatedTransactional() throws Exception { checkCreateNoColumn(REPLICATED, TRANSACTIONAL, false); } /** * Check create when table doesn't exist. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkCreateNoColumn(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); final QueryIndex idx = index(IDX_NAME_1, field(randomString())); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false); } }, IgniteQueryErrorCode.COLUMN_NOT_FOUND); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); } /** * Test index creation on aliased column for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateColumnWithAliasPartitionedAtomic() throws Exception { checkCreateColumnWithAlias(PARTITIONED, ATOMIC, false); } /** * Test index creation on aliased column for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testCreateColumnWithAliasPartitionedAtomicNear() throws Exception { checkCreateColumnWithAlias(PARTITIONED, ATOMIC, true); } /** * Test index creation on aliased column for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateColumnWithAliasPartitionedTransactional() throws Exception { checkCreateColumnWithAlias(PARTITIONED, TRANSACTIONAL, false); } /** * Test index creation on aliased column for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testCreateColumnWithAliasPartitionedTransactionalNear() throws Exception { checkCreateColumnWithAlias(PARTITIONED, TRANSACTIONAL, true); } /** * Test index creation on aliased column for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testCreateColumnWithAliasReplicatedAtomic() throws Exception { checkCreateColumnWithAlias(REPLICATED, ATOMIC, false); } /** * Test index creation on aliased column for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testCreateColumnWithAliasReplicatedTransactional() throws Exception { checkCreateColumnWithAlias(REPLICATED, TRANSACTIONAL, false); } /** * Check index creation on aliased column. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkCreateColumnWithAlias(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_2)); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false); } }, IgniteQueryErrorCode.COLUMN_NOT_FOUND); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); QueryIndex idx = index(IDX_NAME_1, field(alias(FIELD_NAME_2))); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false); assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(alias(FIELD_NAME_2))); assertSimpleIndexOperations(SQL_SIMPLE_FIELD_2); assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_2, SQL_ARG_1); } /** * Test simple index drop for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testDropPartitionedAtomic() throws Exception { checkDrop(PARTITIONED, ATOMIC, false); } /** * Test simple index drop for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testDropPartitionedAtomicNear() throws Exception { checkDrop(PARTITIONED, ATOMIC, true); } /** * Test simple index drop for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testDropPartitionedTransactional() throws Exception { checkDrop(PARTITIONED, TRANSACTIONAL, false); } /** * Test simple index drop for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testDropPartitionedTransactionalNear() throws Exception { checkDrop(PARTITIONED, TRANSACTIONAL, true); } /** * Test simple index drop for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testDropReplicatedAtomic() throws Exception { checkDrop(REPLICATED, ATOMIC, false); } /** * Test simple index drop for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testDropReplicatedTransactional() throws Exception { checkDrop(REPLICATED, TRANSACTIONAL, false); } /** * Check simple index drop. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ public void checkDrop(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); // Create target index. QueryIndex idx1 = index(IDX_NAME_1, field(FIELD_NAME_1)); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx1, false); assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1)); assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1); assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1); // Create another index which must stay intact afterwards. QueryIndex idx2 = index(IDX_NAME_2, field(alias(FIELD_NAME_2))); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx2, false); assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(alias(FIELD_NAME_2))); // Load some data. loadInitialData(); // Drop index. dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1); assertIndexNotUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1); // Make sure the second index is still there. assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(alias(FIELD_NAME_2))); } /** * Test drop when there is no index for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testDropNoIndexPartitionedAtomic() throws Exception { checkDropNoIndex(PARTITIONED, ATOMIC, false); } /** * Test drop when there is no index for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testDropNoIndexPartitionedAtomicNear() throws Exception { checkDropNoIndex(PARTITIONED, ATOMIC, true); } /** * Test drop when there is no index for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testDropNoIndexPartitionedTransactional() throws Exception { checkDropNoIndex(PARTITIONED, TRANSACTIONAL, false); } /** * Test drop when there is no index for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testDropNoIndexPartitionedTransactionalNear() throws Exception { checkDropNoIndex(PARTITIONED, TRANSACTIONAL, true); } /** * Test drop when there is no index for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testDropNoIndexReplicatedAtomic() throws Exception { checkDropNoIndex(REPLICATED, ATOMIC, false); } /** * Test drop when there is no index for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testDropNoIndexReplicatedTransactional() throws Exception { checkDropNoIndex(REPLICATED, TRANSACTIONAL, false); } /** * Check drop when there is no index. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkDropNoIndex(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false); } }, IgniteQueryErrorCode.INDEX_NOT_FOUND); dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, true); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); } /** * Test drop when cache doesn't exist for PARTITIONED ATOMIC cache. * * @throws Exception If failed. */ public void testDropNoCachePartitionedAtomic() throws Exception { checkDropNoCache(PARTITIONED, ATOMIC, false); } /** * Test drop when cache doesn't exist for PARTITIONED ATOMIC cache with near cache. * * @throws Exception If failed. */ public void testDropNoCachePartitionedAtomicNear() throws Exception { checkDropNoCache(PARTITIONED, ATOMIC, true); } /** * Test drop when cache doesn't exist for PARTITIONED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testDropNoCachePartitionedTransactional() throws Exception { checkDropNoCache(PARTITIONED, TRANSACTIONAL, false); } /** * Test drop when cache doesn't exist for PARTITIONED TRANSACTIONAL cache with near cache. * * @throws Exception If failed. */ public void testDropNoCachePartitionedTransactionalNear() throws Exception { checkDropNoCache(PARTITIONED, TRANSACTIONAL, true); } /** * Test drop when cache doesn't exist for REPLICATED ATOMIC cache. * * @throws Exception If failed. */ public void testDropNoCacheReplicatedAtomic() throws Exception { checkDropNoCache(REPLICATED, ATOMIC, false); } /** * Test drop when cache doesn't exist for REPLICATED TRANSACTIONAL cache. * * @throws Exception If failed. */ public void testDropNoCacheReplicatedTransactional() throws Exception { checkDropNoCache(REPLICATED, TRANSACTIONAL, false); } /** * Check drop when cache doesn't exist. * * Check drop when there is no index. * * @param mode Mode. * @param atomicityMode Atomicity mode. * @param near Near flag. * @throws Exception If failed. */ private void checkDropNoCache(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception { initialize(mode, atomicityMode, near); try { queryProcessor(node()).dynamicIndexDrop(randomString(), "my_idx", false).get(); } catch (SchemaOperationException e) { assertEquals(SchemaOperationException.CODE_CACHE_NOT_FOUND, e.code()); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); return; } catch (Exception e) { fail("Unexpected exception: " + e); } fail(SchemaOperationException.class.getSimpleName() + " is not thrown."); } /** * Test that operations fail on LOCAL cache. * * @throws Exception If failed. */ public void testFailOnLocalCache() throws Exception { for (Ignite node : Ignition.allGrids()) { if (!node.configuration().isClientMode()) node.getOrCreateCache(cacheConfiguration().setCacheMode(LOCAL)); } final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1)); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, true); } }, IgniteQueryErrorCode.UNSUPPORTED_OPERATION); assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); assertSchemaException(new RunnableX() { @Override public void run() throws Exception { dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, true); } }, IgniteQueryErrorCode.UNSUPPORTED_OPERATION); } /** * Get node which should be used to start operations. * * @return If failed. */ protected IgniteEx node() { return grid(nodeIndex()); } /** * Get index of the node which should be used to start operations. * * @return If failed. */ protected abstract int nodeIndex(); /** * Get configurations to be used in test. * * @return Configurations. * @throws Exception If failed. */ protected List<IgniteConfiguration> configurations() throws Exception { return Arrays.asList( serverCoordinatorConfiguration(IDX_SRV_CRD), serverConfiguration(IDX_SRV_NON_CRD), clientConfiguration(IDX_CLI), serverConfiguration(IDX_SRV_FILTERED, true), clientConfiguration(IDX_CLI_NEAR_ONLY) ); } /** * Get server coordinator configuration. * * @param idx Index. * @return Configuration. * @throws Exception If failed. */ protected IgniteConfiguration serverCoordinatorConfiguration(int idx) throws Exception { return serverConfiguration(idx); } /** * Assert FIELD_1 index usage. * * @param sql Simple SQL. */ private void assertSimpleIndexOperations(String sql) { for (Ignite node : Ignition.allGrids()) assertSqlSimpleData(node, sql, KEY_BEFORE - SQL_ARG_1); put(node(), KEY_BEFORE, KEY_AFTER); for (Ignite node : Ignition.allGrids()) assertSqlSimpleData(node, sql, KEY_AFTER - SQL_ARG_1); remove(node(), 0, KEY_BEFORE); for (Ignite node : Ignition.allGrids()) assertSqlSimpleData(node, sql, KEY_AFTER - KEY_BEFORE); remove(node(), KEY_BEFORE, KEY_AFTER); for (Ignite node : Ignition.allGrids()) assertSqlSimpleData(node, sql, 0); } /** * Assert composite index usage. * * @param sql Simple SQL. */ private void assertCompositeIndexOperations(String sql) { for (Ignite node : Ignition.allGrids()) assertSqlCompositeData(node, sql, KEY_BEFORE - SQL_ARG_2); put(node(), KEY_BEFORE, KEY_AFTER); for (Ignite node : Ignition.allGrids()) assertSqlCompositeData(node, sql, KEY_AFTER - SQL_ARG_2); remove(node(), 0, KEY_BEFORE); for (Ignite node : Ignition.allGrids()) assertSqlCompositeData(node, sql, KEY_AFTER - KEY_BEFORE); remove(node(), KEY_BEFORE, KEY_AFTER); for (Ignite node : Ignition.allGrids()) assertSqlCompositeData(node, sql, 0); } /** * Ensure that schema exception is thrown. * * @param r Runnable. * @param expCode Error code. */ protected static void assertSchemaException(RunnableX r, int expCode) { try { r.run(); } catch (CacheException e) { Throwable cause = e.getCause(); assertTrue(cause != null); assertTrue("Unexpected cause: " + cause.getClass().getName(), cause instanceof IgniteSQLException); IgniteSQLException cause0 = (IgniteSQLException)cause; int code = cause0.statusCode(); assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + code + ", msg=" + cause.getMessage() + ']', expCode, code); return; } catch (Exception e) { fail("Unexpected exception: " + e); } fail(IgniteSQLException.class.getSimpleName() + " is not thrown."); } /** * Synchronously create index. * * @param space Space. * @param tblName Table name. * @param idx Index. * @param ifNotExists When set to true operation will fail if index already exists. * @throws Exception If failed. */ private void dynamicIndexCreate(String space, String tblName, QueryIndex idx, boolean ifNotExists) throws Exception { GridStringBuilder sql = new SB("CREATE INDEX ") .a(ifNotExists ? "IF NOT EXISTS " : "") .a("\"" + idx.getName() + "\"") .a(" ON ") .a(tblName) .a(" ("); boolean first = true; for (Map.Entry<String, Boolean> fieldEntry : idx.getFields().entrySet()) { if (first) first = false; else sql.a(", "); String name = fieldEntry.getKey(); boolean asc = fieldEntry.getValue(); sql.a("\"" + name + "\"").a(" ").a(asc ? "ASC" : "DESC"); } sql.a(')'); executeSql(space, sql.toString()); } /** * Synchronously drop index. * * @param space Space. * @param idxName Index name. * @param ifExists When set to true operation fill fail if index doesn't exists. * @throws Exception if failed. */ private void dynamicIndexDrop(String space, String idxName, boolean ifExists) throws Exception { String sql = "DROP INDEX " + (ifExists ? "IF EXISTS " : "") + "\"" + idxName + "\""; executeSql(space, sql); } /** * Execute SQL. * * @param space Space. * @param sql SQL. */ private void executeSql(String space, String sql) { log.info("Executing DDL: " + sql); node().cache(space).query(new SqlFieldsQuery(sql)).getAll(); } }