IGNITE-14661 validate parts of compound PK for NOT NULL constraint (#9053)
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 3be9063..1bfff1a 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
@@ -426,8 +426,8 @@
if (uppercaseProps.put(name.toUpperCase(), prop) != null && failOnDuplicate)
throw new IgniteCheckedException("Property with upper cased name '" + name + "' already exists.");
- if ((prop.notNull() && !prop.key() && !prop.name().equals(VAL_FIELD_NAME)) || prop.precision() != -1 ||
- coCtx.kernalContext().config().getSqlConfiguration().isValidationEnabled()) {
+ if ((prop.notNull() && !prop.name().equals(KEY_FIELD_NAME) && !prop.name().equals(VAL_FIELD_NAME))
+ || prop.precision() != -1 || coCtx.kernalContext().config().getSqlConfiguration().isValidationEnabled()) {
if (validateProps == null)
validateProps = new ArrayList<>();
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheSqlInsertValidationSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheSqlInsertValidationSelfTest.java
index 00f6f25..a966d97 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheSqlInsertValidationSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheSqlInsertValidationSelfTest.java
@@ -24,7 +24,9 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+
import org.apache.ignite.IgniteCache;
+import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
@@ -43,6 +45,9 @@
* Tests for validation of inserts sql queries.
*/
public class IgniteCacheSqlInsertValidationSelfTest extends AbstractIndexingCommonTest {
+ /** Name of the class that actually not in class path. */
+ private static final String TEST_CLASS_NAME = "MyClass";
+
/** Entry point for sql api. Contains table configurations too. */
private static IgniteCache<Object, Object> cache;
@@ -101,7 +106,9 @@
.addQueryField("fv2", "java.lang.Long", null)
.setTableName("INT_KEY_TAB"),
new QueryEntity(SuperKey.class, String.class)
- .setTableName("SUPER_TAB")
+ .setTableName("SUPER_TAB"),
+ new QueryEntity(String.class.getName(), TEST_CLASS_NAME)
+ .setTableName("MY_CLASS")
)), "testCache");
}
@@ -204,6 +211,44 @@
}
/**
+ * Check we can't insert null as column value of a compound PK that has NOT NULL constraint.
+ */
+ @Test
+ public void testValidationOfCompoundKey() {
+ execute("CREATE TABLE PUBLIC.TBL (id1 BIGINT, id2 BIGINT NOT NULL, val BIGINT, PRIMARY KEY(id1, id2))");
+
+ GridTestUtils.assertThrows(log(),
+ () -> execute("INSERT INTO PUBLIC.TBL VALUES (1, null, 3)"),
+ IgniteSQLException.class,
+ "Null value is not allowed for column 'ID2'");
+ }
+
+ /**
+ * Check that raw _KEY and _VAL skipped on validation, hence exception
+ * is not thrown when their classes is not in class path.
+ */
+ @Test
+ public void testValidationSkippedForRawKeyVal() {
+ String key = "foo";
+
+ BinaryObject bo = grid(0).binary().builder(TEST_CLASS_NAME)
+ .setField(key, "bar")
+ .build();
+
+ IgniteCache<Object, Object> binCache = cache.withKeepBinary();
+
+ binCache.put(key, bo);
+
+ List<List<?>> res = binCache.query(new SqlFieldsQuery("SELECT _val FROM MY_CLASS WHERE _key = ?")
+ .setArgs(key)).getAll();
+
+ assertEquals(1, res.size());
+ assertEquals(1, res.get(0).size());
+ assertTrue(res.get(0).get(0) instanceof BinaryObject);
+ assertEquals(bo.field(key), ((BinaryObject)res.get(0).get(0)).field(key));
+ }
+
+ /**
* Execute native sql.
*
* @param sql query.