Description
Issue
Adding new primitive type columns to the existing tables which have data existed in
Cassandra causes Ignite to raise an exception (see below) in Ignite 2.7.0 or
2.8.0 nightly build when loading the data from Cassandra into Ignite Cache
store. This works before Ignite 2.6, and even apache-ignite-fabric-2.7.0.20180918 nightly build.
The assumption seems not correct because both Ignite and Cassandra are (key, value) store. In fact, SQLLINE tool, we don't need to insert into primitive value, see the example blow -
CREATE TABLE aa (col1 int PRIMARY KEY, col2 double );
INSERT INTO aa(col1) VALUES (1);
SELECT * FROM aa;
Root Cause
This issue is related to the implementation of public static Object getCassandraColumnValue(Row row, String col, Class clazz, Serializer serializer) in PropertyMappingHelper.java (https://github.com/apache/ignite/blob/master/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/common/PropertyMappingHelper.java). This class has been changed since 2.7.0. For primitive java type, I don't think we need to check null value. The assumption is that every row for primitive types in Cassandra table must have value is not correct.
public static Object getCassandraColumnValue(Row row, String col, Class clazz, Serializer serializer) {
...
if (Long.class.equals(clazz))
return row.isNull(col) ? null : row.getLong(col);
// why needs to check the primitive null. NoSql is a pair of (key, value).
// there is no pair in this case
// all databases (relational databases and NoSql databases support null colum values)
if (long.class.equals(clazz)) {
if (row.isNull(col))
return row.getLong(col);
}
}
Detailed Exception
[2019-03-11
09:44:34,352][ERROR]cassandra-cache-loader-#61%ignite-procurant-purchase-order-cluster%[CassandraCacheStore]
Failed to build Ignite value object from provided Cassandra row
java.lang.IllegalArgumentException: Can't cast null value from Cassandra
table column 'suppliertotamt' to double value used in domain object model
at
org.apache.ignite.cache.store.cassandra.common.PropertyMappingHelper.getCassandraColumnValue(PropertyMappingHelper.java:169)
at
org.apache.ignite.cache.store.cassandra.persistence.PojoField.setValueFromRow(PojoField.java:205)
at
org.apache.ignite.cache.store.cassandra.persistence.PersistenceController.buildObject(PersistenceController.java:405)
at
org.apache.ignite.cache.store.cassandra.persistence.PersistenceController.buildValueObject(PersistenceController.java:227)
at
org.apache.ignite.cache.store.cassandra.session.LoadCacheCustomQueryWorker$1.process(LoadCacheCustomQueryWorker.java:107)
at
org.apache.ignite.cache.store.cassandra.session.CassandraSessionImpl.execute(CassandraSessionImpl.java:402)
at
org.apache.ignite.cache.store.cassandra.session.LoadCacheCustomQueryWorker.call(LoadCacheCustomQueryWorker.java:81)
at
org.apache.ignite.cache.store.cassandra.session.LoadCacheCustomQueryWorker.call(LoadCacheCustomQueryWorker.java:35)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[2019-03-11
09:44:34,360][ERROR]cassandra-cache-loader-#61%ignite-procurant-purchase-order-cluster%[CassandraCacheStore]
Failed to execute Cassandra loadCache operation
class org.apache.ignite.IgniteException: Failed to execute Cassandra
loadCache operation
at
org.apache.ignite.cache.store.cassandra.session.CassandraSessionImpl.execute(CassandraSessionImpl.java:415)
at
org.apache.ignite.cache.store.cassandra.session.LoadCacheCustomQueryWorker.call(LoadCacheCustomQueryWorker.java:81)
at
org.apache.ignite.cache.store.cassandra.session.LoadCacheCustomQueryWorker.call(LoadCacheCustomQueryWorker.java:35)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: class org.apache.ignite.IgniteException: Failed to build Ignite
value object from provided Cassandra row
at
org.apache.ignite.cache.store.cassandra.session.LoadCacheCustomQueryWorker$1.process(LoadCacheCustomQueryWorker.java:112)
at
org.apache.ignite.cache.store.cassandra.session.CassandraSessionImpl.execute(CassandraSessionImpl.java:402)
... 6 more
Caused by: java.lang.IllegalArgumentException: Can't cast null value from
Cassandra table column 'suppliertotamt' to double value used in domain
object model
at
org.apache.ignite.cache.store.cassandra.common.PropertyMappingHelper.getCassandraColumnValue(PropertyMappingHelper.java:169)
at
org.apache.ignite.cache.store.cassandra.persistence.PojoField.setValueFromRow(PojoField.java:205)
at
org.apache.ignite.cache.store.cassandra.persistence.PersistenceController.buildObject(PersistenceController.java:405)
at
org.apache.ignite.cache.store.cassandra.persistence.PersistenceController.buildValueObject(PersistenceController.java:227)