This is an automated email from the ASF dual-hosted git repository.
ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 921f974d5d IGNITE-23157 Improve column value type validation when
serializing Tuples (#4414)
921f974d5d is described below
commit 921f974d5df35af9c35cca1d731ffe85c4f25365
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Thu Sep 19 06:48:03 2024 +0300
IGNITE-23157 Improve column value type validation when serializing Tuples
(#4414)
* Fix NPE when assertions are disabled
* Throw `MarshallerException` with descriptive message
* Add test for client and embedded modes
---
.../client/proto/ClientBinaryTupleUtils.java | 19 ++++++++++++++++---
.../app/client/ItThinClientMarshallingTest.java | 19 +++++++++++++++++++
.../schema/marshaller/TupleMarshallerImpl.java | 20 +++++++++++++++++---
3 files changed, 52 insertions(+), 6 deletions(-)
diff --git
a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
index 5b30458977..db638b21f3 100644
---
a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
+++
b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
@@ -39,7 +39,9 @@ import
org.apache.ignite.internal.binarytuple.BinaryTupleReader;
import org.apache.ignite.internal.type.NativeType;
import org.apache.ignite.internal.type.NativeTypeSpec;
import org.apache.ignite.internal.type.NativeTypes;
+import org.apache.ignite.lang.ErrorGroups.Marshalling;
import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.lang.MarshallerException;
import org.apache.ignite.sql.ColumnType;
import org.jetbrains.annotations.Nullable;
@@ -120,7 +122,7 @@ public class ClientBinaryTupleUtils {
}
}
- static Function<Integer, Object> readerForType(BinaryTupleReader binTuple,
ColumnType type) {
+ private static Function<Integer, Object> readerForType(BinaryTupleReader
binTuple, ColumnType type) {
switch (type) {
case INT8:
return binTuple::byteValue;
@@ -436,8 +438,19 @@ public class ClientBinaryTupleUtils {
}
} catch (ClassCastException e) {
NativeType nativeType = NativeTypes.fromObject(v);
- // A null is handled separately, so nativeType should not be null.
- assert nativeType != null;
+
+ if (nativeType == null) {
+ // Unsupported type (does not map to any Ignite type) - throw
(same behavior as embedded).
+ throw new MarshallerException(
+ UUID.randomUUID(),
+ Marshalling.COMMON_ERR,
+ String.format(
+ "Invalid value type provided for column
[name='%s', expected='%s', actual='%s']",
+ name,
+ type.javaClass().getName(),
+ v.getClass().getName()),
+ e);
+ }
NativeTypeSpec actualType = nativeType.spec();
NativeTypeSpec expectedType = NativeTypeSpec.fromColumnType(type);
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientMarshallingTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientMarshallingTest.java
index cc3c1608c6..e41b6279db 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientMarshallingTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientMarshallingTest.java
@@ -28,6 +28,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import java.math.BigDecimal;
import org.apache.ignite.Ignite;
import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.lang.MarshallerException;
+import org.apache.ignite.table.RecordView;
import org.apache.ignite.table.Table;
import org.apache.ignite.table.Tuple;
import org.apache.ignite.table.mapper.Mapper;
@@ -355,6 +357,23 @@ public class ItThinClientMarshallingTest extends
ItAbstractThinClientTest {
assertThat(ex.getMessage(), containsString("Numeric field overflow in
column 'VAL'"));
}
+ @Test
+ public void testUnsupportedObjectInTuple() {
+ Table table = ignite().tables().table(TABLE_NAME);
+ RecordView<Tuple> tupleView = table.recordView();
+
+ Tuple rec = Tuple.create()
+ .set("KEY", 1)
+ .set("VAL", new TestPojo2());
+
+ MarshallerException ex = assertThrows(MarshallerException.class, () ->
tupleView.upsert(null, rec));
+
+ assertEquals(
+ "Invalid value type provided for column [name='VAL',
expected='java.lang.String', actual='"
+ + TestPojo2.class.getName() + "']",
+ ex.getMessage());
+ }
+
private static class TestPojo2 {
public int key;
diff --git
a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshallerImpl.java
b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshallerImpl.java
index 30bfe749d2..1055764cd4 100644
---
a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshallerImpl.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshallerImpl.java
@@ -25,6 +25,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import org.apache.ignite.internal.binarytuple.BinaryTupleCommon;
import org.apache.ignite.internal.binarytuple.BinaryTupleContainer;
import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
@@ -39,6 +40,7 @@ import org.apache.ignite.internal.schema.row.RowAssembler;
import org.apache.ignite.internal.type.DecimalNativeType;
import org.apache.ignite.internal.type.NativeType;
import org.apache.ignite.internal.type.NativeTypeSpec;
+import org.apache.ignite.lang.ErrorGroups.Marshalling;
import org.apache.ignite.lang.MarshallerException;
import org.apache.ignite.table.Tuple;
import org.apache.ignite.table.TupleHelper;
@@ -214,9 +216,21 @@ public class TupleMarshallerImpl implements
TupleMarshaller {
if (val != null) {
if (!colType.spec().fixedLength()) {
- val = shrinkValue(val, col.type());
-
- estimatedValueSize += getValueSize(val, colType);
+ try {
+ val = shrinkValue(val, col.type());
+
+ estimatedValueSize += getValueSize(val, colType);
+ } catch (ClassCastException e) {
+ throw new MarshallerException(
+ UUID.randomUUID(),
+ Marshalling.COMMON_ERR,
+ String.format(
+ "Invalid value type provided for
column [name='%s', expected='%s', actual='%s']",
+ col.name(),
+
col.type().spec().asColumnType().javaClass().getName(),
+ val.getClass().getName()),
+ e);
+ }
}
}