Copilot commented on code in PR #7319:
URL: https://github.com/apache/ignite-3/pull/7319#discussion_r2663961951


##########
modules/api/src/main/java/org/apache/ignite/table/TupleImpl.java:
##########
@@ -437,4 +437,26 @@ public String toString() {
 
         return b.toString();
     }
+
+    private <T> T valueNotNull(int columnIndex) {
+        T value = value(columnIndex);
+
+        if (value == null) {
+            throw new NullPointerException("The value of field at index " + 
columnIndex
+                    + " is null and cannot be converted to a primitive data 
type.");
+        }

Review Comment:
   The error messages in TupleImpl are hardcoded and inconsistent with the 
error message constants defined in IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE 
and IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE. While TupleImpl is in 
the public API module and cannot depend on internal modules, the error messages 
should be consistent across all implementations for a better user experience. 
Consider defining these error message constants in a location accessible to the 
API module, or duplicating them as constants in TupleImpl to ensure consistency 
and maintainability.



##########
modules/client/src/test/java/org/apache/ignite/client/ClientTupleTest.java:
##########
@@ -339,6 +350,59 @@ public void testToStringMatchesTupleImpl() {
                 clientTuple.toString().replace("ClientTuple ", ""));
     }
 
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("primitiveAccessors")
+    @SuppressWarnings("ThrowableNotThrown")
+    void nullPointerWhenReadingNullAsPrimitive(
+            NativeType type,
+            BiConsumer<Tuple, Object> fieldAccessor
+    ) {
+        SchemaDescriptor schema = new SchemaDescriptor(
+                1,
+                new Column[]{new Column("ID", INT32, false)},
+                new Column[]{new Column("VAL", type, true)}
+        );
+
+        ClientSchema clientSchema = new ClientSchema(
+                1,
+                new ClientColumn[] {
+                        new ClientColumn("ID", ColumnType.INT32, false, 0, -1, 
-1, 0),
+                        new ClientColumn("VAL", type.spec(), true, -1, 0, -1, 
1),
+                },
+                marshallers
+        );
+
+        BinaryRow binaryRow = SchemaTestUtils.binaryRow(schema, 1, null);
+        Tuple row = new ClientTuple(clientSchema, TuplePart.KEY_AND_VAL, new 
BinaryTupleReader(schema.length(), binaryRow.tupleSlice()));
+
+        assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 1),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 1)
+        );
+
+        assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, "VAL"),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE, 
"VAL")
+        );
+
+        row.set("NEW", null);
+
+        assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 2),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 2)
+

Review Comment:
   There is an inconsistent trailing blank line inside the assertThrows call. 
For consistency with the rest of the codebase, this blank line should be 
removed.
   ```suggestion
   
   ```



##########
modules/api/src/main/java/org/apache/ignite/table/TupleImpl.java:
##########
@@ -437,4 +437,26 @@ public String toString() {
 
         return b.toString();
     }
+
+    private <T> T valueNotNull(int columnIndex) {
+        T value = value(columnIndex);
+
+        if (value == null) {
+            throw new NullPointerException("The value of field at index " + 
columnIndex
+                    + " is null and cannot be converted to a primitive data 
type.");
+        }
+
+        return value;
+    }
+
+    private <T> T valueNotNull(String columnName) {
+        T value = value(columnName);
+
+        if (value == null) {
+            throw new NullPointerException("The value of field '" + columnName
+                    + "' is null and cannot be converted to a primitive data 
type.");
+        }

Review Comment:
   The error messages in TupleImpl are hardcoded and inconsistent with the 
error message constants defined in IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE 
and IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE. While TupleImpl is in 
the public API module and cannot depend on internal modules, the error messages 
should be consistent across all implementations for a better user experience. 
Consider defining these error message constants in a location accessible to the 
API module, or duplicating them as constants in TupleImpl to ensure consistency 
and maintainability.



##########
modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java:
##########
@@ -495,6 +508,78 @@ public void testFullSchemaHasAllTypes() {
         }
     }
 
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("primitiveAccessors")
+    @SuppressWarnings("ThrowableNotThrown")
+    void nullPointerWhenReadingNullAsPrimitive(
+            NativeType type,
+            BiConsumer<Tuple, Object> fieldAccessor
+    ) {
+        SchemaDescriptor schema = new SchemaDescriptor(
+                1,
+                new Column[]{new Column("KEY", INT32, false)},
+                new Column[]{new Column("VAL", type, true)}
+        );
+
+        SchemaDescriptor schema2 = applyAddingValueColumn(schema, 1, new 
Column("NEW", type, true));
+
+        Tuple tuple = Tuple.create().set("KEY", 1).set("VAL", null);
+        TupleMarshaller marshaller = 
KeyValueTestUtils.createMarshaller(schema);
+
+        Row binRow = marshaller.marshal(tuple);
+        Tuple row = TableRow.tuple(binRow);
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 1),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 1)
+        );
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, "VAL"),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE, 
"VAL")
+
+        );

Review Comment:
   There is an inconsistent trailing blank line inside the assertThrows call. 
For consistency with the rest of the codebase, this blank line should be 
removed.



##########
modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java:
##########
@@ -495,6 +508,78 @@ public void testFullSchemaHasAllTypes() {
         }
     }
 
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("primitiveAccessors")
+    @SuppressWarnings("ThrowableNotThrown")
+    void nullPointerWhenReadingNullAsPrimitive(
+            NativeType type,
+            BiConsumer<Tuple, Object> fieldAccessor
+    ) {
+        SchemaDescriptor schema = new SchemaDescriptor(
+                1,
+                new Column[]{new Column("KEY", INT32, false)},
+                new Column[]{new Column("VAL", type, true)}
+        );
+
+        SchemaDescriptor schema2 = applyAddingValueColumn(schema, 1, new 
Column("NEW", type, true));
+
+        Tuple tuple = Tuple.create().set("KEY", 1).set("VAL", null);
+        TupleMarshaller marshaller = 
KeyValueTestUtils.createMarshaller(schema);
+
+        Row binRow = marshaller.marshal(tuple);
+        Tuple row = TableRow.tuple(binRow);
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 1),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 1)
+        );
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, "VAL"),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE, 
"VAL")
+
+        );
+
+        // Modify row.
+        row.set("NEW", null);
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 2),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 2)
+
+        );

Review Comment:
   There is an inconsistent trailing blank line inside the assertThrows call. 
For consistency with the rest of the codebase, this blank line should be 
removed.



##########
modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java:
##########
@@ -495,6 +508,78 @@ public void testFullSchemaHasAllTypes() {
         }
     }
 
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("primitiveAccessors")
+    @SuppressWarnings("ThrowableNotThrown")
+    void nullPointerWhenReadingNullAsPrimitive(
+            NativeType type,
+            BiConsumer<Tuple, Object> fieldAccessor
+    ) {
+        SchemaDescriptor schema = new SchemaDescriptor(
+                1,
+                new Column[]{new Column("KEY", INT32, false)},
+                new Column[]{new Column("VAL", type, true)}
+        );
+
+        SchemaDescriptor schema2 = applyAddingValueColumn(schema, 1, new 
Column("NEW", type, true));
+
+        Tuple tuple = Tuple.create().set("KEY", 1).set("VAL", null);
+        TupleMarshaller marshaller = 
KeyValueTestUtils.createMarshaller(schema);
+
+        Row binRow = marshaller.marshal(tuple);
+        Tuple row = TableRow.tuple(binRow);
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 1),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 1)
+        );
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, "VAL"),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE, 
"VAL")
+
+        );
+
+        // Modify row.
+        row.set("NEW", null);
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, 2),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 2)
+
+        );
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(row, "NEW"),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_NAMED_ERROR_MESSAGE, 
"NEW")
+        );
+
+        // Upgrade original row
+        var schemaRegistry = new SchemaRegistryImpl(
+                v -> v == 1 ? schema : schema2,
+                schema2
+        );
+
+        Tuple upgradedRow = TableRow.tuple(schemaRegistry.resolve(binRow, 
schema2));
+
+        IgniteTestUtils.assertThrows(
+                NullPointerException.class,
+                () -> fieldAccessor.accept(upgradedRow, 2),
+                
IgniteStringFormatter.format(IgniteUtils.NULL_TO_PRIMITIVE_ERROR_MESSAGE, 2)
+
+        );

Review Comment:
   There is an inconsistent trailing blank line inside the assertThrows call. 
For consistency with the rest of the codebase, this blank line should be 
removed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to