You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2020/07/20 13:05:48 UTC
[ignite] branch master updated: IGNITE-13110 Add validation of SQL
field types on cache put - Fixes #8055.
This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 2e8d5a7 IGNITE-13110 Add validation of SQL field types on cache put - Fixes #8055.
2e8d5a7 is described below
commit 2e8d5a7c32b04e43ae5411d9c39dcd5f7585c343
Author: Sergey Kalashnikov <zk...@gmail.com>
AuthorDate: Mon Jul 20 17:45:18 2020 +0500
IGNITE-13110 Add validation of SQL field types on cache put - Fixes #8055.
Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
.../ignite/configuration/SqlConfiguration.java | 25 ++
.../processors/query/QueryTypeDescriptorImpl.java | 37 ++-
...SqlFieldTypeValidationOnKeyValueInsertTest.java | 325 +++++++++++++++++++++
.../query/SqlFieldTypeValidationTypesTest.java | 202 +++++++++++++
.../IgniteBinaryCacheQueryTestSuite.java | 6 +-
5 files changed, 587 insertions(+), 8 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/SqlConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/SqlConfiguration.java
index e3dd475..6b297cd 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/SqlConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/SqlConfiguration.java
@@ -45,6 +45,9 @@ public class SqlConfiguration {
/** SQL query history size. */
private int sqlQryHistSize = DFLT_SQL_QUERY_HISTORY_SIZE;
+ /** Enable validation of key & values against sql schema. */
+ private boolean validationEnabled;
+
/**
* Defines the default query timeout.
*
@@ -147,6 +150,28 @@ public class SqlConfiguration {
return this;
}
+ /**
+ * Is key & value validation enabled.
+ *
+ * @return {@code true} When key & value shall be validated against SQL schema.
+ */
+ public boolean isValidationEnabled() {
+ return validationEnabled;
+ }
+
+ /**
+ * Enable/disable key & value validation.
+ *
+ * @param validationEnabled {@code true} When key & value shall be validated against SQL schema.
+ * Default value is {@code false}.
+ * @return {@code this} for chaining.
+ */
+ public SqlConfiguration setValidationEnabled(boolean validationEnabled) {
+ this.validationEnabled = validationEnabled;
+
+ return this;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(SqlConfiguration.class, this);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
index fb0b664..21e0154 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.query;
import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -36,6 +37,7 @@ import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.KEY_SCALE_OUT_OF_RANGE;
@@ -420,13 +422,8 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
if (uppercaseProps.put(name.toUpperCase(), prop) != null && failOnDuplicate)
throw new IgniteCheckedException("Property with upper cased name '" + name + "' already exists.");
- if (prop.notNull()) {
- if (validateProps == null)
- validateProps = new ArrayList<>();
-
- validateProps.add(prop);
- }
- else if (prop.precision() != -1) {
+ if (prop.notNull() || prop.precision() != -1 ||
+ coCtx.kernalContext().config().getSqlConfiguration().isValidationEnabled()) {
if (validateProps == null)
validateProps = new ArrayList<>();
@@ -583,6 +580,8 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
if (F.isEmpty(validateProps))
return;
+ final boolean validateTypes = coCtx.kernalContext().config().getSqlConfiguration().isValidationEnabled();
+
for (int i = 0; i < validateProps.size(); ++i) {
GridQueryProperty prop = validateProps.get(i);
@@ -606,6 +605,30 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
isKey ? NULL_KEY : NULL_VALUE);
}
+ if (validateTypes && propVal != null) {
+ if (!(propVal instanceof BinaryObject)) {
+ if (!U.box(prop.type()).isAssignableFrom(U.box(propVal.getClass()))) {
+ // Some reference type arrays end up being converted to Object[]
+ if (!(prop.type().isArray() && Object[].class == propVal.getClass() &&
+ Arrays.stream((Object[]) propVal).
+ noneMatch(x -> x != null && !U.box(prop.type().getComponentType()).isAssignableFrom(U.box(x.getClass())))))
+ {
+ throw new IgniteSQLException("Type for a column '" + prop.name() +
+ "' is not compatible with table definition. Expected '" +
+ prop.type().getSimpleName() + "', actual type '" +
+ propVal.getClass().getSimpleName() + "'");
+ }
+ }
+ }
+ else if (coCtx.kernalContext().cacheObjects().typeId(prop.type().getName()) !=
+ ((BinaryObject)propVal).type().typeId()) {
+ throw new IgniteSQLException("Type for a column '" + prop.name() +
+ "' is not compatible with table definition. Expected '" +
+ prop.type().getSimpleName() + "', actual type '" +
+ ((BinaryObject)propVal).type().typeName() + "'");
+ }
+ }
+
if (propVal == null || prop.precision() == -1)
continue;
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlFieldTypeValidationOnKeyValueInsertTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlFieldTypeValidationOnKeyValueInsertTest.java
new file mode 100644
index 0000000..b215e18
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlFieldTypeValidationOnKeyValueInsertTest.java
@@ -0,0 +1,325 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.cache.processor.EntryProcessor;
+import javax.cache.processor.EntryProcessorResult;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.binary.BinaryBasicNameMapper;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.BinaryConfiguration;
+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.index.AbstractIndexingCommonTest;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+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;
+
+/**
+ *
+ */
+@RunWith(Parameterized.class)
+public class SqlFieldTypeValidationOnKeyValueInsertTest extends AbstractIndexingCommonTest {
+ /** */
+ private static final String SQL_TEXT = "select id, name from Person where id=1";
+
+ /** */
+ private static final String ERROR = "Type for a column 'NAME' is not compatible with table definition.";
+
+ /** */
+ private static boolean validate;
+
+ /** */
+ @Parameterized.Parameter(0)
+ public CacheMode cacheMode;
+
+ /** */
+ @Parameterized.Parameter(1)
+ public CacheAtomicityMode atomicityMode;
+
+ /** */
+ @Parameterized.Parameter(2)
+ public boolean near;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.getSqlConfiguration().setValidationEnabled(validate);
+
+ cfg.setCacheConfiguration(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+ .setCacheMode(cacheMode)
+ .setAtomicityMode(atomicityMode)
+ .setNearConfiguration(near ? new NearCacheConfiguration<>().setNearStartSize(1) : null)
+ .setQueryEntities(Collections.singletonList(
+ new QueryEntity()
+ .setKeyFieldName("id")
+ .setValueType("Person")
+ .setFields(new LinkedHashMap<>(
+ F.asMap("id", "java.lang.Integer",
+ "name", "java.util.UUID"))))));
+
+ cfg.setBinaryConfiguration(new BinaryConfiguration().setNameMapper(new BinaryBasicNameMapper(true)));
+
+ return cfg;
+ }
+
+ /** */
+ @Parameterized.Parameters(name = "{index} {0} {1} {2}")
+ public static List<Object[]> data() {
+ List<Object[]> res = new ArrayList<>();
+
+ res.add(new Object[] {REPLICATED, TRANSACTIONAL, true});
+ res.add(new Object[] {REPLICATED, TRANSACTIONAL, false});
+ res.add(new Object[] {REPLICATED, ATOMIC, true});
+ res.add(new Object[] {REPLICATED, ATOMIC, false});
+ res.add(new Object[] {PARTITIONED, TRANSACTIONAL, true});
+ res.add(new Object[] {PARTITIONED, TRANSACTIONAL, false});
+ res.add(new Object[] {PARTITIONED, ATOMIC, true});
+ res.add(new Object[] {PARTITIONED, ATOMIC, false});
+
+ return res;
+ }
+
+ /** */
+ @After
+ public void tearDown() {
+ stopAllGrids();
+ }
+
+ /** */
+ @Test
+ public void testError() throws Exception {
+ validate = true;
+
+ startGrids(2);
+
+ IgniteEx clnt = startClientGrid(2);
+
+ IgniteCache<Object, Object> cache = clnt.cache(DEFAULT_CACHE_NAME);
+
+ BinaryObject obj = clnt.binary().builder("Person")
+ .setField("id", 1)
+ .setField("name", UUID.randomUUID().toString())
+ .build();
+
+ doInsertsError(cache, obj);
+ }
+
+ /** */
+ @Test
+ public void testSuccess() throws Exception {
+ validate = true;
+
+ startGrids(2);
+
+ IgniteEx clnt = startClientGrid(2);
+
+ IgniteCache<Object, Object> cache = clnt.cache(DEFAULT_CACHE_NAME).withKeepBinary();
+
+ BinaryObject obj = clnt.binary().builder("Person")
+ .setField("id", 1)
+ .setField("name", UUID.randomUUID())
+ .build();
+
+ doInsertSuccess(cache, obj);
+
+ assertEquals(obj, cache.withKeepBinary().get(1));
+
+ grid(0).context().query()
+ .querySqlFields(
+ new SqlFieldsQuery(SQL_TEXT).setSchema(DEFAULT_CACHE_NAME), true)
+ .getAll();
+ }
+
+ /** */
+ @Test
+ public void testSkipValidation() throws Exception {
+ validate = false;
+
+ startGrids(2);
+
+ IgniteEx clnt = startClientGrid(2);
+
+ IgniteCache<Object, Object> cache = clnt.cache(DEFAULT_CACHE_NAME).withKeepBinary();
+
+ BinaryObject obj = clnt.binary().builder("Person")
+ .setField("id", 1)
+ .setField("name", UUID.randomUUID().toString())
+ .build();
+
+ doInsertSuccess(cache, obj);
+
+ assertEquals(obj, cache.withKeepBinary().get(1));
+ }
+
+ /** */
+ @Test
+ public void testClassInstanceError() throws Exception {
+ validate = true;
+
+ startGrids(2);
+
+ IgniteEx clnt = startClientGrid(2);
+
+ IgniteCache<Object, Object> cache = clnt.cache(DEFAULT_CACHE_NAME);
+
+ doInsertsError(cache, new Person(UUID.randomUUID().toString()));
+ }
+
+ /** */
+ @Test
+ public void testClassInstanceSkipValidation() throws Exception {
+ validate = false;
+
+ startGrids(2);
+
+ IgniteEx clnt = startClientGrid(2);
+
+ IgniteCache<Object, Object> cache = clnt.cache(DEFAULT_CACHE_NAME);
+
+ Person obj = new Person(UUID.randomUUID().toString());
+
+ doInsertSuccess(cache, obj);
+
+ assertEquals(obj, cache.get(1));
+ }
+
+ /** */
+ private void doInsertsError(IgniteCache<Object, Object> cache, Object obj) {
+ assertThrows(() -> cache.put(1, obj), ERROR);
+
+ assertThrows(() -> cache.putAll(F.asMap(1, obj, 2, obj)), ERROR);
+
+ assertThrows(() -> cache.putIfAbsent(1, obj), ERROR);
+
+ assertThrows(() -> cache.invoke(1, new TestEntryProcessor(obj)), ERROR);
+
+ assertThrows(() -> cache.invokeAll(
+ F.asMap(1, new TestEntryProcessor(obj), 2, new TestEntryProcessor(obj))).get(1).get(),
+ ERROR);
+
+ assertThrows(() -> cache.replace(1, obj), ERROR);
+
+ assertThrows(() -> cache.getAndPut(1, obj), ERROR);
+
+ assertThrows(() -> cache.getAndPutIfAbsent(1, obj), ERROR);
+
+ assertThrows(() -> cache.getAndReplace(1, obj), ERROR);
+ }
+
+ /** */
+ private void assertThrows(GridTestUtils.RunnableX runx, String msg) {
+ try {
+ runx.runx();
+ }
+ catch (Exception e) {
+ if (X.hasCause(e, msg, Throwable.class))
+ return;
+
+ throw new AssertionError("Unexpected exception ", e);
+ }
+
+ throw new AssertionError("Exception has not been thrown.");
+ }
+
+ /** */
+ private void doInsertSuccess(IgniteCache<Object, Object> cache, Object obj) {
+ cache.put(1, obj);
+
+ cache.putAll(F.asMap(1, obj, 2, obj));
+
+ cache.putIfAbsent(1, obj);
+
+ cache.invoke(1, new TestEntryProcessor(obj));
+
+ Map<Object, EntryProcessorResult<Void>> m =
+ cache.invokeAll(F.asMap(1, new TestEntryProcessor(obj), 2, new TestEntryProcessor(obj)));
+
+ assertTrue(m == null || m.isEmpty());
+
+ cache.replace(1, obj);
+
+ cache.getAndPut(1, obj);
+
+ cache.getAndPutIfAbsent(1, obj);
+
+ cache.getAndReplace(1, obj);
+ }
+
+ /** */
+ public static class Person {
+ /** */
+ private final Object name;
+
+ /** */
+ public Person(Object name) {
+ this.name = name;
+ }
+
+ /** */
+ public Object name() {
+ return name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object obj) {
+ return obj instanceof Person && F.eq(((Person) obj).name, name);
+ }
+ }
+
+ /** */
+ public static class TestEntryProcessor implements EntryProcessor<Object, Object, Void> {
+ /** */
+ private final Object val;
+
+ /** */
+ public TestEntryProcessor(Object val) {
+ this.val = val;
+ }
+
+ /** */
+ @Override public Void process(MutableEntry<Object, Object> entry, Object... args) {
+ entry.setValue(val);
+
+ return null;
+ }
+ }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlFieldTypeValidationTypesTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlFieldTypeValidationTypesTest.java
new file mode 100644
index 0000000..800ac21
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlFieldTypeValidationTypesTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.UUID;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryBasicNameMapper;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.configuration.BinaryConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ *
+ */
+@RunWith(Parameterized.class)
+public class SqlFieldTypeValidationTypesTest extends AbstractIndexingCommonTest {
+ /** */
+ private static final String ERROR = "Type for a column 'NAME' is not compatible with table definition.";
+
+ /** */
+ @Parameterized.Parameter(0)
+ public Class<?> fieldType;
+
+ /** */
+ @Parameterized.Parameter(1)
+ public Object okVal;
+
+ /** */
+ @Parameterized.Parameter(2)
+ public Object errVal;
+
+ /** */
+ @Parameterized.Parameter(3)
+ public boolean indexed;
+
+ /** */
+ private static boolean validate;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.getSqlConfiguration().setValidationEnabled(validate);
+
+ cfg.setCacheConfiguration(new CacheConfiguration<>(DEFAULT_CACHE_NAME).setQueryEntities(
+ Collections.singletonList(
+ new QueryEntity()
+ .setKeyFieldName("id")
+ .setValueType("Person")
+ .setFields(new LinkedHashMap<>(
+ F.asMap("id", "java.lang.Integer",
+ "name", fieldType.getName())))
+ .setIndexes(indexed ? Collections.singletonList(new QueryIndex("name")) : null)
+ )));
+
+ cfg.setBinaryConfiguration(new BinaryConfiguration().setNameMapper(new BinaryBasicNameMapper(true)));
+
+ return cfg;
+ }
+
+ /** */
+ @Parameterized.Parameters(name = "{index} type={0} idx={3}")
+ public static List<Object[]> data() {
+ List<Object[]> res = new ArrayList<>();
+
+ // Type, ok value, error value, indexed flag.
+ res.add(new Object[] {Integer.class, 1, "1", false});
+ res.add(new Object[] {Integer.class, 1, "1", true});
+
+ res.add(new Object[] {String.class, "1", 1, false});
+ res.add(new Object[] {String.class, "1", 1, true});
+
+ res.add(new Object[] {UUID.class, UUID.randomUUID(), UUID.randomUUID().toString(), false});
+ res.add(new Object[] {UUID.class, UUID.randomUUID(), UUID.randomUUID().toString(), true});
+
+ res.add(new Object[] {TestEnum.class, TestEnum.A, "C", false});
+ res.add(new Object[] {TestEnum.class, TestEnum.A, "C", true});
+
+ res.add(new Object[] {Integer[].class, new Integer[] {0,1}, new String[] {"0", "1"}, false});
+ res.add(new Object[] {Integer[].class, new Integer[] {0,1}, new String[] {"0", "1"}, true});
+
+ res.add(new Object[] {int[].class, new Integer[] {0,1}, new String[] {"0", "1"}, false});
+ res.add(new Object[] {int[].class, new Integer[] {0,1}, new String[] {"0", "1"}, true});
+
+ res.add(new Object[] {int[].class, new Object[] {0,1}, new Object[] {"0", "1"}, false});
+ res.add(new Object[] {int[].class, new Object[] {0,1}, new Object[] {"0", "1"}, true});
+
+ return res;
+ }
+
+ /** */
+ @After
+ public void tearDown() {
+ stopAllGrids();
+ }
+
+ /** */
+ @Test
+ public void testError() throws Exception {
+ validate = true;
+
+ startGrid(0);
+
+ IgniteCache<Object, Object> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+ BinaryObject obj = grid(0).binary().builder("Person")
+ .setField("id", 1)
+ .setField("name", errVal)
+ .build();
+
+ GridTestUtils.assertThrows(log, () -> cache.put(1, obj), IgniteException.class, ERROR);
+
+ assertNull(cache.withKeepBinary().get(1));
+ }
+
+ /** */
+ @Test
+ public void testClassInstanceError() throws Exception {
+ validate = true;
+
+ startGrid(0);
+
+ IgniteCache<Object, Object> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+ GridTestUtils.assertThrows(log, () -> cache.put(1, new Person(errVal)), IgniteException.class, ERROR);
+
+ assertNull(cache.withKeepBinary().get(1));
+ }
+
+ /** */
+ private boolean expectIndexFail() {
+ return indexed && (UUID.class == fieldType || Integer.class == fieldType);
+ }
+
+ /** */
+ public static class Person {
+ /** */
+ private final Object name;
+
+ /** */
+ public Person(Object name) {
+ this.name = name;
+ }
+
+ /** */
+ public Object name() {
+ return name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object obj) {
+ if (!(obj instanceof Person))
+ return false;
+
+ if (name instanceof Object[])
+ return Arrays.equals((Object[])name, (Object[])((Person) obj).name);
+
+ return F.eq(name, ((Person) obj).name);
+ }
+ }
+
+ /**
+ *
+ */
+ public enum TestEnum {
+ /** */
+ A,
+
+ /** */
+ B
+ }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
index 992eb03..a846f24 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
@@ -219,6 +219,8 @@ import org.apache.ignite.internal.processors.query.KillQueryOnClientDisconnectTe
import org.apache.ignite.internal.processors.query.KillQueryTest;
import org.apache.ignite.internal.processors.query.MultipleStatementsSqlQuerySelfTest;
import org.apache.ignite.internal.processors.query.RunningQueriesTest;
+import org.apache.ignite.internal.processors.query.SqlFieldTypeValidationOnKeyValueInsertTest;
+import org.apache.ignite.internal.processors.query.SqlFieldTypeValidationTypesTest;
import org.apache.ignite.internal.processors.query.SqlIllegalSchemaSelfTest;
import org.apache.ignite.internal.processors.query.SqlIncompatibleDataTypeExceptionTest;
import org.apache.ignite.internal.processors.query.SqlMergeOnClientNodeTest;
@@ -623,8 +625,10 @@ import org.junit.runners.Suite;
IgniteCacheMergeSqlQuerySelfTest.class,
SqlMergeTest.class,
- SqlMergeOnClientNodeTest.class
+ SqlMergeOnClientNodeTest.class,
+ SqlFieldTypeValidationTypesTest.class,
+ SqlFieldTypeValidationOnKeyValueInsertTest.class
})
public class IgniteBinaryCacheQueryTestSuite {
}