Skip to content

Commit

Permalink
IGNITE-11219: SQL: Fixed affinity mapper resolution for CREATE TABLE …
Browse files Browse the repository at this point in the history
…templates. This closes apache#6046.

(cherry picked from commit 2a19e3f)
  • Loading branch information
Max-Pudov committed Feb 27, 2019
1 parent 4f27dd0 commit dbf9a59
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,9 @@ else if (QueryUtils.TEMPLATE_REPLICATED.equalsIgnoreCase(templateName))
ccfg.setSqlEscapeAll(true);
ccfg.setQueryEntities(Collections.singleton(entity));

if (!QueryUtils.isCustomAffinityMapper(ccfg.getAffinityMapper()))
ccfg.setAffinityMapper(null);

if (affinityKey != null)
ccfg.setKeyConfiguration(new CacheKeyConfiguration(entity.getKeyType(), affinityKey));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,18 @@ public static void checkNotNullAllowed(CacheConfiguration cfg) {
"is set.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}

/**
* Checks whether affinity key mapper is custom or default.
*
* @param affinityKeyMapper Affinity key mapper.
* @return {@code true} if affinity key mapper is custom.
*/
public static boolean isCustomAffinityMapper(AffinityKeyMapper affinityKeyMapper) {
return affinityKeyMapper != null &&
!(affinityKeyMapper instanceof CacheDefaultBinaryAffinityKeyMapper) &&
!(affinityKeyMapper instanceof GridCacheDefaultAffinityKeyMapper);
}

/**
* Checks if given column can be removed from table using its {@link QueryEntity}.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* 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.query;

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.binary.BinaryObjectBuilder;
import org.apache.ignite.cache.affinity.AffinityKeyMapper;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;

/**
* Ensures that SQL queries work for tables created dynamically based on a template.
*/
public class IgniteSqlCreateTableTemplateTest extends GridCommonAbstractTest {
/** {@inheritDoc} */
@Override public IgniteConfiguration getConfiguration(String name) throws Exception {
IgniteConfiguration configuration = new IgniteConfiguration();
configuration.setIgniteInstanceName(name);

CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();

defaultCacheConfiguration.setName("DEFAULT_TEMPLATE*");

CacheConfiguration customCacheConfiguration = new CacheConfiguration();

customCacheConfiguration.setName("CUSTOM_TEMPLATE*");

MockAffinityKeyMapper customAffinityMapper = new MockAffinityKeyMapper();

customCacheConfiguration.setAffinityMapper(customAffinityMapper);

configuration.setCacheConfiguration(defaultCacheConfiguration, customCacheConfiguration);

return configuration;
}

/** {@inheritDoc} */
@SuppressWarnings("deprecation")
@Override protected void beforeTestsStarted() throws Exception {
startGrid();
}

/**
* Tests select statement works on a table with BinaryObject as a primary key.
*/
@Test
public void testSelectForTableWithDataInsertedWithKeyValueAPI() {
Ignite ignite = grid();
IgniteCache cache = ignite.getOrCreateCache("test");

createTable(cache, "PERSON", "DEFAULT_TEMPLATE");

createTable(cache, "ORGANIZATION", "DEFAULT_TEMPLATE");

BinaryObjectBuilder keyBuilder = ignite.binary().builder("PERSON_KEY");

keyBuilder.setField("ID", 1);
keyBuilder.setField("AFF_PERSON", 2);

BinaryObjectBuilder valueBuilder = ignite.binary().builder("PERSON_VALUE");
valueBuilder.setField("NAME", "test");

ignite.cache("PERSON_CACHE").withKeepBinary().put(keyBuilder.build(), valueBuilder.build());

keyBuilder = ignite.binary().builder("ORGANIZATION_KEY");

keyBuilder.setField("ID", 1);
keyBuilder.setField("AFF_ORGANIZATION", 2);

valueBuilder = ignite.binary().builder("ORGANIZATION_VALUE");

valueBuilder.setField("NAME", "test");

ignite.cache("ORGANIZATION_CACHE").withKeepBinary().put(keyBuilder.build(), valueBuilder.build());

assertEquals(1, ignite.cache("PERSON_CACHE").query(
new SqlFieldsQuery("Select NAME from PERSON where ID = 1")).getAll().size()
);

assertEquals(1, ignite.cache("PERSON_CACHE").query(
new SqlFieldsQuery("Select NAME from PERSON where AFF_PERSON = 2")).getAll().size()
);

assertEquals(1, ignite.cache("ORGANIZATION_CACHE").query(
new SqlFieldsQuery("Select NAME from ORGANIZATION where AFF_ORGANIZATION = 2")).getAll().size()
);

}

/**
* Creates table based on a template.
*
* @param cache Cache.
*/
private void createTable(IgniteCache cache, String tableName, String template) {
String sql = String.format(
"CREATE TABLE IF NOT EXISTS %1$s(\n" +
" ID INT NOT NULL,\n" +
" AFF_%1$s INT NOT NULL,\n" +
" NAME VARCHAR2(100),\n" +
" PRIMARY KEY (ID, AFF_%1$s)\n" +
") with \"TEMPLATE=%2$s,KEY_TYPE=%1$s_KEY, AFFINITY_KEY=AFF_%1$s, CACHE_NAME=%1$s_CACHE, " +
"VALUE_TYPE=%1$s_VALUE, ATOMICITY=TRANSACTIONAL\";", tableName, template);

cache.query(new SqlFieldsQuery(sql).setSchema("PUBLIC"));
}

/**
* When template has custom affinity mapper.
* then cache created via CREATE TABLE command should have the same affinity mapper.
*/
@SuppressWarnings("unchecked")
@Test
public void testCustomAffinityKeyMapperIsNotOverwritten() {
Ignite ignite = grid();

IgniteCache cache = ignite.getOrCreateCache("test");

createTable(cache, "CUSTOM", "CUSTOM_TEMPLATE");

assertTrue(ignite.getOrCreateCache("CUSTOM_CACHE").getConfiguration(
CacheConfiguration.class).getAffinityMapper() instanceof MockAffinityKeyMapper);
}

/**
* Mock affinity mapper implementation.
*/
@SuppressWarnings("deprecation")
private static class MockAffinityKeyMapper implements AffinityKeyMapper {
/** {@inheritDoc} */
@Override public Object affinityKey(Object key) {
return null;
}

/** {@inheritDoc} */
@Override public void reset() {
// no-op
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import junit.framework.TestSuite;
import org.apache.ignite.internal.processors.cache.IgniteCacheQueriesLoadTest1;
import org.apache.ignite.internal.processors.query.IgniteSqlCreateTableTemplateTest;

/**
* Cache query suite with binary marshaller.
Expand All @@ -32,6 +33,7 @@ public static TestSuite suite() throws Exception {
TestSuite suite = IgniteCacheQuerySelfTestSuite2.suite();

suite.addTestSuite(IgniteCacheQueriesLoadTest1.class);
suite.addTestSuite(IgniteSqlCreateTableTemplateTest.class);

return suite;
}
Expand Down

0 comments on commit dbf9a59

Please sign in to comment.