blob: d061a16898ed6c15b68bdbcffa6a8f3d4024e340 [file] [log] [blame]
/*
* 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 java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import javax.cache.CacheException;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.QueryIndex;
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.lang.RunnableX;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.testframework.junits.WithSystemProperty;
import org.junit.Test;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK;
import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
/**
* Tests for dynamic index creation.
*/
@SuppressWarnings({"unchecked"})
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;
/** Cache. */
protected static final String STATIC_CACHE_NAME = "cache_static";
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
for (IgniteConfiguration cfg : configurations())
Ignition.start(cfg);
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
node().context().cache().dynamicDestroyCache(CACHE_NAME, true, true, false, null).get();
super.afterTest();
}
/**
* Initialize cache for tests.
*
* @param mode Mode.
* @param atomicityMode Atomicity mode.
* @param near Near flag.
* @throws Exception If failed.
*/
private void initialize(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near)
throws Exception {
createSqlCache(node(), cacheConfiguration(mode, atomicityMode, near));
awaitPartitionMapExchange();
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.
*/
@Test
public void testCreatePartitionedAtomic() throws Exception {
checkCreate(PARTITIONED, ATOMIC, false);
}
/**
* Test simple index create for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreatePartitionedAtomicNear() throws Exception {
checkCreate(PARTITIONED, ATOMIC, true);
}
/**
* Test simple index create for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreatePartitionedTransactional() throws Exception {
checkCreate(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Test simple index create for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreatePartitionedTransactionalNear() throws Exception {
checkCreate(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test simple index create for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateReplicatedAtomic() throws Exception {
checkCreate(REPLICATED, ATOMIC, false);
}
/**
* Test simple index create for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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_ESCAPED));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
assertIgniteSqlException(new RunnableX() {
@Override public void runx() throws Exception {
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
}
}, IgniteQueryErrorCode.INDEX_ALREADY_EXISTS);
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, true, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
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.
*/
@Test
public void testCreateCompositePartitionedAtomic() throws Exception {
checkCreateComposite(PARTITIONED, ATOMIC, false);
}
/**
* Test composite index creation for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateCompositePartitionedAtomicNear() throws Exception {
checkCreateComposite(PARTITIONED, ATOMIC, true);
}
/**
* Test composite index creation for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateCompositePartitionedTransactional() throws Exception {
checkCreateComposite(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Test composite index creation for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateCompositePartitionedTransactionalNear() throws Exception {
checkCreateComposite(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test composite index creation for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateCompositeReplicatedAtomic() throws Exception {
checkCreateComposite(REPLICATED, ATOMIC, false);
}
/**
* Test composite index creation for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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_ESCAPED), field(alias(FIELD_NAME_2_ESCAPED)));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE,
field(FIELD_NAME_1_ESCAPED), field(alias(FIELD_NAME_2_ESCAPED)));
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.
*/
@Test
public void testCreateIndexNoCachePartitionedAtomic() throws Exception {
checkCreateNotCache(PARTITIONED, ATOMIC, false);
}
/**
* Test create when cache doesn't exist for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoCachePartitionedAtomicNear() throws Exception {
checkCreateNotCache(PARTITIONED, ATOMIC, true);
}
/**
* Test create when cache doesn't exist for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoCachePartitionedTransactional() throws Exception {
checkCreateNotCache(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Test create when cache doesn't exist for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoCachePartitionedTransactionalNear() throws Exception {
checkCreateNotCache(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test create when cache doesn't exist for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoCacheReplicatedAtomic() throws Exception {
checkCreateNotCache(REPLICATED, ATOMIC, false);
}
/**
* Test create when cache doesn't exist for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoCacheReplicatedTransactional() 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_ESCAPED));
try {
String cacheName = randomString();
queryProcessor(node()).dynamicIndexCreate(cacheName, cacheName, TBL_NAME, idx, false, 0).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.
*/
@Test
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.
*/
@Test
public void testCreateNoTablePartitionedAtomicNear() throws Exception {
checkCreateNoTable(PARTITIONED, ATOMIC, true);
}
/**
* Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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.
*/
@Test
public void testCreateNoTablePartitionedTransactionalNear() throws Exception {
checkCreateNoTable(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test create when table doesn't exist for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateNoTableReplicatedAtomic() throws Exception {
checkCreateNoTable(REPLICATED, ATOMIC, false);
}
/**
* Test create when table doesn't exist for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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_ESCAPED));
assertIgniteSqlException(new RunnableX() {
@Override public void runx() throws Exception {
dynamicIndexCreate(CACHE_NAME, randomString(), idx, false, 0);
}
}, 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.
*/
@Test
public void testCreateIndexNoColumnPartitionedAtomic() throws Exception {
checkCreateIndexNoColumn(PARTITIONED, ATOMIC, false);
}
/**
* Test create when table doesn't exist for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoColumnPartitionedAtomicNear() throws Exception {
checkCreateIndexNoColumn(PARTITIONED, ATOMIC, true);
}
/**
* Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoColumnPartitionedTransactional() throws Exception {
checkCreateIndexNoColumn(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Test create when table doesn't exist for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoColumnPartitionedTransactionalNear() throws Exception {
checkCreateIndexNoColumn(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test create when table doesn't exist for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoColumnReplicatedAtomic() throws Exception {
checkCreateIndexNoColumn(REPLICATED, ATOMIC, false);
}
/**
* Test create when table doesn't exist for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexNoColumnReplicatedTransactional() throws Exception {
checkCreateIndexNoColumn(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 checkCreateIndexNoColumn(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception {
initialize(mode, atomicityMode, near);
final QueryIndex idx = index(IDX_NAME_1, field(randomString()));
assertIgniteSqlException(new RunnableX() {
@Override public void runx() throws Exception {
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
}
}, 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.
*/
@Test
public void testCreateIndexOnColumnWithAliasPartitionedAtomic() throws Exception {
checkCreateIndexOnColumnWithAlias(PARTITIONED, ATOMIC, false);
}
/**
* Test index creation on aliased column for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexOnColumnWithAliasPartitionedAtomicNear() throws Exception {
checkCreateIndexOnColumnWithAlias(PARTITIONED, ATOMIC, true);
}
/**
* Test index creation on aliased column for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateIndexOnColumnWithAliasPartitionedTransactional() throws Exception {
checkCreateIndexOnColumnWithAlias(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Test index creation on aliased column for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateColumnWithAliasPartitionedTransactionalNear() throws Exception {
checkCreateIndexOnColumnWithAlias(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test index creation on aliased column for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateColumnWithAliasReplicatedAtomic() throws Exception {
checkCreateIndexOnColumnWithAlias(REPLICATED, ATOMIC, false);
}
/**
* Test index creation on aliased column for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testCreateColumnWithAliasReplicatedTransactional() throws Exception {
checkCreateIndexOnColumnWithAlias(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 checkCreateIndexOnColumnWithAlias(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near)
throws Exception {
initialize(mode, atomicityMode, near);
assertIgniteSqlException(new RunnableX() {
@Override public void runx() throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_2_ESCAPED));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
}
}, IgniteQueryErrorCode.COLUMN_NOT_FOUND);
assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
QueryIndex idx = index(IDX_NAME_1, field(alias(FIELD_NAME_2_ESCAPED)));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(alias(FIELD_NAME_2_ESCAPED)));
assertSimpleIndexOperations(SQL_SIMPLE_FIELD_2);
assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_2, SQL_ARG_1);
}
/**
* Tests creating index with inline size for PARTITIONED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithInlineSizePartitionedAtomic() throws Exception {
checkCreateIndexWithInlineSize(PARTITIONED, ATOMIC, false);
}
/**
* Tests creating index with inline size for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithInlineSizePartitionedAtomicNear() throws Exception {
checkCreateIndexWithInlineSize(PARTITIONED, ATOMIC, true);
}
/**
* Tests creating index with inline size for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithInlineSizePartitionedTransactional() throws Exception {
checkCreateIndexWithInlineSize(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Tests creating index with inline size for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithInlineSizePartitionedTransactionalNear() throws Exception {
checkCreateIndexWithInlineSize(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Tests creating index with inline size for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithInlineSizeReplicatedAtomic() throws Exception {
checkCreateIndexWithInlineSize(REPLICATED, ATOMIC, false);
}
/**
* Tests creating index with inline size option for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithInlineSizeReplicatedTransactional() throws Exception {
checkCreateIndexWithInlineSize(REPLICATED, TRANSACTIONAL, false);
}
/**
* Checks that inline size parameter is correctly handled during index creation.
*
* @param mode Mode.
* @param atomicityMode Atomicity mode.
* @param near Near flag.
* @throws Exception If failed.
*/
private void checkCreateIndexWithInlineSize(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near)
throws Exception {
initialize(mode, atomicityMode, near);
checkNoIndexIsCreatedForInlineSize(-2, IgniteQueryErrorCode.PARSING);
checkNoIndexIsCreatedForInlineSize(Integer.MIN_VALUE, IgniteQueryErrorCode.PARSING);
checkIndexCreatedForInlineSize(0);
loadInitialData();
checkIndexCreatedForInlineSize(1);
loadInitialData();
checkIndexCreatedForInlineSize(Integer.MAX_VALUE);
}
/**
* Verifies that index is created with the specified inline size.
*
* @param inlineSize Inline size to put into CREATE INDEX
* @throws Exception If failed.
*/
private void checkIndexCreatedForInlineSize(int inlineSize) throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
idx.setInlineSize(inlineSize);
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, inlineSize, field(FIELD_NAME_1_ESCAPED));
assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1);
assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false);
assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
}
/**
* Verifies that no index is created and an exception is thrown.
*
* @param inlineSize Inline size value in the CREATE INDEX statement.
* @param igniteQryErrorCode Expected error code in the thrown exception.
* @throws Exception If failed for any other reason than the expected exception.
*/
private void checkNoIndexIsCreatedForInlineSize(final int inlineSize, int igniteQryErrorCode) throws Exception {
assertIgniteSqlException(new RunnableX() {
@Override public void runx() throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
idx.setInlineSize(inlineSize);
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
}
}, igniteQryErrorCode);
assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
}
/**
* Tests creating index with parallelism for PARTITIONED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithParallelismPartitionedAtomic() throws Exception {
checkCreateIndexWithParallelism(PARTITIONED, ATOMIC, false);
}
/**
* Tests creating index with parallelism for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithParallelismPartitionedAtomicNear() throws Exception {
checkCreateIndexWithParallelism(PARTITIONED, ATOMIC, true);
}
/**
* Tests creating index with parallelism for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithParallelismPartitionedTransactional() throws Exception {
checkCreateIndexWithParallelism(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Tests creating index with parallelism for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithParallelismPartitionedTransactionalNear() throws Exception {
checkCreateIndexWithParallelism(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Tests creating index with parallelism for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithParallelismReplicatedAtomic() throws Exception {
checkCreateIndexWithParallelism(REPLICATED, ATOMIC, false);
}
/**
* Tests creating index with parallelism option for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, value = "true")
public void testCreateIndexWithParallelismReplicatedTransactional() throws Exception {
checkCreateIndexWithParallelism(REPLICATED, TRANSACTIONAL, false);
}
/**
* Checks that parallelism parameter is correctly handled during index creation.
*
* @param mode Mode.
* @param atomicityMode Atomicity mode.
* @param near Near flag.
* @throws Exception If failed.
*/
private void checkCreateIndexWithParallelism(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near)
throws Exception {
initialize(mode, atomicityMode, near);
checkNoIndexIsCreatedForParallelism(-2, IgniteQueryErrorCode.PARSING);
checkNoIndexIsCreatedForParallelism(Integer.MIN_VALUE, IgniteQueryErrorCode.PARSING);
checkIndexCreatedForParallelism(0);
loadInitialData();
checkIndexCreatedForParallelism(1);
loadInitialData();
checkIndexCreatedForParallelism(5);
}
/**
* Verifies that index was created properly with different parallelism levels.
* NOTE! Unfortunately we cannot check the real parallelism level on which this index was created because it should
* use internal API. But we can check if this index was created properly on different parallelism levels.
*
* @param parallel Parallelism level to put into CREATE INDEX
* @throws Exception If failed.
*/
private void checkIndexCreatedForParallelism(int parallel) throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, parallel);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1);
assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false);
assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
}
/**
* Verifies that no index is created and an exception is thrown.
*
* @param parallel Parallelism level in the CREATE INDEX statement.
* @param igniteQryErrorCode Expected error code in the thrown exception.
* @throws Exception If failed for any other reason than the expected exception.
*/
private void checkNoIndexIsCreatedForParallelism(final int parallel, int igniteQryErrorCode) throws Exception {
assertIgniteSqlException(new RunnableX() {
@Override public void runx() throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, parallel);
}
}, igniteQryErrorCode);
assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
}
/**
* Test simple index drop for PARTITIONED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropPartitionedAtomic() throws Exception {
checkDrop(PARTITIONED, ATOMIC, false);
}
/**
* Test simple index drop for PARTITIONED ATOMIC cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropPartitionedAtomicNear() throws Exception {
checkDrop(PARTITIONED, ATOMIC, true);
}
/**
* Test simple index drop for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropPartitionedTransactional() throws Exception {
checkDrop(PARTITIONED, TRANSACTIONAL, false);
}
/**
* Test simple index drop for PARTITIONED TRANSACTIONAL cache with near cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropPartitionedTransactionalNear() throws Exception {
checkDrop(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test simple index drop for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropReplicatedAtomic() throws Exception {
checkDrop(REPLICATED, ATOMIC, false);
}
/**
* Test simple index drop for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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_ESCAPED));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx1, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
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_ESCAPED)));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx2, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE, field(alias(FIELD_NAME_2_ESCAPED)));
// 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, QueryIndex.DFLT_INLINE_SIZE, field(alias(FIELD_NAME_2_ESCAPED)));
}
/**
* Test drop when there is no index for PARTITIONED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
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.
*/
@Test
public void testDropNoIndexPartitionedAtomicNear() throws Exception {
checkDropNoIndex(PARTITIONED, ATOMIC, true);
}
/**
* Test drop when there is no index for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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.
*/
@Test
public void testDropNoIndexPartitionedTransactionalNear() throws Exception {
checkDropNoIndex(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test drop when there is no index for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropNoIndexReplicatedAtomic() throws Exception {
checkDropNoIndex(REPLICATED, ATOMIC, false);
}
/**
* Test drop when there is no index for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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);
assertIgniteSqlException(new RunnableX() {
@Override public void runx() 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.
*/
@Test
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.
*/
@Test
public void testDropNoCachePartitionedAtomicNear() throws Exception {
checkDropNoCache(PARTITIONED, ATOMIC, true);
}
/**
* Test drop when cache doesn't exist for PARTITIONED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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.
*/
@Test
public void testDropNoCachePartitionedTransactionalNear() throws Exception {
checkDropNoCache(PARTITIONED, TRANSACTIONAL, true);
}
/**
* Test drop when cache doesn't exist for REPLICATED ATOMIC cache.
*
* @throws Exception If failed.
*/
@Test
public void testDropNoCacheReplicatedAtomic() throws Exception {
checkDropNoCache(REPLICATED, ATOMIC, false);
}
/**
* Test drop when cache doesn't exist for REPLICATED TRANSACTIONAL cache.
*
* @throws Exception If failed.
*/
@Test
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 {
String cacheName = randomString();
queryProcessor(node()).dynamicIndexDrop(cacheName, cacheName, "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 work on statically configured cache.
*
* @throws Exception If failed.
*/
@Test
public void testNonSqlCache() throws Exception {
final QueryIndex idx = index(IDX_NAME_2, field(FIELD_NAME_1));
dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true, 0);
assertIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
dynamicIndexDrop(STATIC_CACHE_NAME, IDX_NAME_1, true);
assertNoIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1);
}
/**
* Test behavior depending on index name case sensitivity.
*/
@Test
public void testIndexNameCaseSensitivity() throws Exception {
doTestIndexNameCaseSensitivity("myIdx", false);
doTestIndexNameCaseSensitivity("myIdx", true);
}
/**
* Perform a check on given index name considering case sensitivity.
* @param idxName Index name to check.
* @param sensitive Whether index should be created w/case sensitive name or not.
*/
private void doTestIndexNameCaseSensitivity(String idxName, boolean sensitive) throws Exception {
String idxNameSql = (sensitive ? '"' + idxName + '"' : idxName);
// This one should always work.
assertIndexNameIsValid(idxNameSql, idxNameSql);
if (sensitive) {
assertIndexNameIsNotValid(idxNameSql, idxName.toUpperCase());
assertIndexNameIsNotValid(idxNameSql, idxName.toLowerCase());
}
else {
assertIndexNameIsValid(idxNameSql, '"' + idxName.toUpperCase() + '"');
assertIndexNameIsValid(idxNameSql, idxName.toUpperCase());
assertIndexNameIsValid(idxNameSql, idxName.toLowerCase());
}
}
/**
* Check that given variant of index name works for DDL context.
* @param idxNameToCreate Name of the index to use in {@code CREATE INDEX}.
* @param checkedIdxName Index name to use in actual check.
*/
private void assertIndexNameIsValid(String idxNameToCreate, String checkedIdxName) throws Exception {
info("Checking index name variant for validity: " + checkedIdxName);
final QueryIndex idx = index(idxNameToCreate, field(FIELD_NAME_1));
dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true, 0);
dynamicIndexDrop(STATIC_CACHE_NAME, checkedIdxName, false);
}
/**
* Check that given variant of index name works for DDL context.
* @param idxNameToCreate Name of the index to use in {@code CREATE INDEX}.
* @param checkedIdxName Index name to use in actual check.
*/
private void assertIndexNameIsNotValid(String idxNameToCreate, final String checkedIdxName) throws Exception {
info("Checking index name variant for invalidity: " + checkedIdxName);
final QueryIndex idx = index(idxNameToCreate, field(FIELD_NAME_1));
dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true, 0);
assertThrows(null, new Callable<Object>() {
@Override public Object call() throws Exception {
dynamicIndexDrop(STATIC_CACHE_NAME, checkedIdxName, false);
return null;
}
}, IgniteSQLException.class, "Index doesn't exist: " + checkedIdxName.toUpperCase());
}
/**
* 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)
);
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration commonConfiguration(int idx) throws Exception {
IgniteConfiguration cfg = super.commonConfiguration(idx);
if (idx != nodeIndex())
return cfg;
CacheConfiguration staticCacheCfg = cacheConfiguration().setName(STATIC_CACHE_NAME);
((QueryEntity)staticCacheCfg.getQueryEntities().iterator().next()).setIndexes(Collections.singletonList(index(
IDX_NAME_1, field(FIELD_NAME_1)
)));
CacheConfiguration[] newCfgs = new CacheConfiguration[F.isEmpty(cfg.getCacheConfiguration()) ? 1 :
cfg.getCacheConfiguration().length + 1];
if (newCfgs.length > 1)
System.arraycopy(cfg.getCacheConfiguration(), 0, newCfgs, 0, newCfgs.length - 1);
newCfgs[newCfgs.length - 1] = staticCacheCfg;
cfg.setCacheConfiguration(newCfgs);
return cfg;
}
/**
* 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 assertIgniteSqlException(Runnable r, int expCode) {
assertIgniteSqlException(r, null, expCode);
}
/**
* Ensure that schema exception is thrown.
*
* @param r Runnable.
* @param msg Exception message to expect, or {@code null} if it can be waived.
* @param expCode Error code.
*/
private static void assertIgniteSqlException(Runnable r, String msg, int expCode) {
try {
r.run();
}
catch (IgniteException ie) {
assertTrue("Unexpected exception: " + ie, ie.getCause() instanceof CacheException);
checkCacheException(msg, expCode, (CacheException)ie.getCause());
return;
}
catch (CacheException e) {
checkCacheException(msg, expCode, e);
return;
}
catch (Exception e) {
fail("Unexpected exception: " + e);
}
fail(IgniteSQLException.class.getSimpleName() + " is not thrown.");
}
/** */
private static void checkCacheException(String msg, int expCode, 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);
if (msg != null)
assertEquals("Unexpected error message [expected=" + msg + ", actual=" + cause0.getMessage() + ']',
msg, cause0.getMessage());
}
/**
* Synchronously create index.
*
* @param cacheName Cache name.
* @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 cacheName, String tblName, QueryIndex idx, boolean ifNotExists, int parallel)
throws Exception {
dynamicIndexCreate(node(), cacheName, tblName, idx, ifNotExists, parallel);
}
/**
* Synchronously drop index.
*
* @param cacheName Cache name.
* @param idxName Index name.
* @param ifExists When set to true operation will fail if index doesn't exists.
* @throws Exception if failed.
*/
private void dynamicIndexDrop(String cacheName, String idxName, boolean ifExists) throws Exception {
dynamicIndexDrop(node(), cacheName, idxName, ifExists);
}
}