exceptionfactory commented on a change in pull request #5388:
URL: https://github.com/apache/nifi/pull/5388#discussion_r710100686



##########
File path: 
nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java
##########
@@ -298,7 +272,67 @@ private DataType getDataType(final int sqlType, final 
ResultSet rs, final int co
         }
     }
 
-    private static DataType getArrayBaseType(final Array array) throws 
SQLException {
+    private DataType determineDataTypeToReturn(DataType dataType, boolean 
useLogicalTypes) {
+        RecordFieldType fieldType = dataType.getFieldType();
+        if (!useLogicalTypes
+                && (fieldType == RecordFieldType.DECIMAL
+                || fieldType == RecordFieldType.DATE
+                || fieldType == RecordFieldType.TIME
+                || fieldType == RecordFieldType.TIMESTAMP)) {
+            return RecordFieldType.STRING.getDataType();
+        } else {
+            return dataType;
+        }
+    }
+
+    private DataType getArrayDataType(ResultSet rs, int columnIndex, boolean 
useLogicalTypes) throws SQLException {
+        // The JDBC API does not allow us to know what the base type of an 
array is through the metadata.
+        // As a result, we have to obtain the actual Array for this record. 
Once we have this, we can determine
+        // the base type. However, if the base type is, itself, an array, we 
will simply return a base type of
+        // String because otherwise, we need the ResultSet for the array 
itself, and many JDBC Drivers do not
+        // support calling Array.getResultSet() and will throw an Exception if 
that is not supported.
+        try {
+            final Array array = rs.getArray(columnIndex);
+
+            if (array == null) {
+                return 
RecordFieldType.ARRAY.getArrayDataType(RecordFieldType.STRING.getDataType());
+            }
+            final DataType baseType = getArrayBaseType(array, useLogicalTypes);
+            return RecordFieldType.ARRAY.getArrayDataType(baseType);
+        } catch (SQLFeatureNotSupportedException sfnse) {
+            return 
RecordFieldType.ARRAY.getArrayDataType(RecordFieldType.STRING.getDataType());
+        }
+    }
+
+    private DataType getDecimalDataType(ResultSet rs, int columnIndex) throws 
SQLException {

Review comment:
       Recommend `final`:
   ```suggestion
       private DataType getDecimalDataType(final ResultSet rs, final int 
columnIndex) throws SQLException {
   ```

##########
File path: 
nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java
##########
@@ -298,7 +272,67 @@ private DataType getDataType(final int sqlType, final 
ResultSet rs, final int co
         }
     }
 
-    private static DataType getArrayBaseType(final Array array) throws 
SQLException {
+    private DataType determineDataTypeToReturn(DataType dataType, boolean 
useLogicalTypes) {
+        RecordFieldType fieldType = dataType.getFieldType();
+        if (!useLogicalTypes
+                && (fieldType == RecordFieldType.DECIMAL
+                || fieldType == RecordFieldType.DATE
+                || fieldType == RecordFieldType.TIME
+                || fieldType == RecordFieldType.TIMESTAMP)) {
+            return RecordFieldType.STRING.getDataType();
+        } else {
+            return dataType;
+        }
+    }
+
+    private DataType getArrayDataType(ResultSet rs, int columnIndex, boolean 
useLogicalTypes) throws SQLException {

Review comment:
       Recommend adding `final` to these parameters:
   ```suggestion
       private DataType getArrayDataType(final ResultSet rs, final int 
columnIndex, final boolean useLogicalTypes) throws SQLException {
   ```

##########
File path: 
nifi-commons/nifi-record/src/test/java/org/apache/nifi/serialization/record/ResultSetRecordSetTest.java
##########
@@ -272,6 +278,76 @@ public void 
testCreateSchemaArrayThrowsNotSupportedException() throws SQLExcepti
         
assertEquals(RecordFieldType.ARRAY.getArrayDataType(RecordFieldType.STRING.getDataType()),
 resultSchema.getField(0).getDataType());
     }
 
+    @Test
+    public void testCreateSchemaWithLogicalTypes() throws SQLException {
+        testCreateSchemaLogicalTypes(true);
+    }
+
+    @Test
+    public void testCreateSchemaNoLogicalTypes() throws SQLException {
+        testCreateSchemaLogicalTypes(false);
+    }
+
+    private void testCreateSchemaLogicalTypes(boolean useLogicalTypes) throws 
SQLException {
+        // GIVEN
+        Object[][] columns = new Object[][] {

Review comment:
       This structure seems difficult to maintain as it requires precise index 
references in other methods.  It seems like it would be better and easier to 
use one or or Maps with more precise types.  Another option might be a List of 
a custom objects declared in this test class.

##########
File path: 
nifi-commons/nifi-record/src/test/java/org/apache/nifi/serialization/record/ResultSetRecordSetTest.java
##########
@@ -272,6 +278,76 @@ public void 
testCreateSchemaArrayThrowsNotSupportedException() throws SQLExcepti
         
assertEquals(RecordFieldType.ARRAY.getArrayDataType(RecordFieldType.STRING.getDataType()),
 resultSchema.getField(0).getDataType());
     }
 
+    @Test
+    public void testCreateSchemaWithLogicalTypes() throws SQLException {
+        testCreateSchemaLogicalTypes(true);
+    }
+
+    @Test
+    public void testCreateSchemaNoLogicalTypes() throws SQLException {
+        testCreateSchemaLogicalTypes(false);
+    }
+
+    private void testCreateSchemaLogicalTypes(boolean useLogicalTypes) throws 
SQLException {
+        // GIVEN
+        Object[][] columns = new Object[][] {
+                {1, COLUMN_NAME_DATE, Types.DATE, 
RecordFieldType.DATE.getDataType()},
+                {2, "time", Types.TIME, RecordFieldType.TIME.getDataType()},
+                {3, "time_with_timezone", Types.TIME_WITH_TIMEZONE, 
RecordFieldType.TIME.getDataType()},
+                {4, "timestamp", Types.TIMESTAMP, 
RecordFieldType.TIMESTAMP.getDataType()},
+                {5, "timestamp_with_timezone", Types.TIMESTAMP_WITH_TIMEZONE, 
RecordFieldType.TIMESTAMP.getDataType()},
+                {6, COLUMN_NAME_BIG_DECIMAL_1, 
Types.DECIMAL,RecordFieldType.DECIMAL.getDecimalDataType(7, 3)},
+                {7, COLUMN_NAME_BIG_DECIMAL_2, Types.NUMERIC, 
RecordFieldType.DECIMAL.getDecimalDataType(4, 0)},
+                {8, COLUMN_NAME_BIG_DECIMAL_3, Types.JAVA_OBJECT, 
RecordFieldType.DECIMAL.getDecimalDataType(501, 1)},
+                {9, COLUMN_NAME_BIG_DECIMAL_4, Types.DECIMAL, 
RecordFieldType.DECIMAL.getDecimalDataType(10, 3)},
+                {10, COLUMN_NAME_BIG_DECIMAL_5, Types.DECIMAL, 
RecordFieldType.DECIMAL.getDecimalDataType(3, 10)}
+        };
+        final RecordSchema recordSchema = givenRecordSchema(columns);
+
+        ResultSetMetaData resultSetMetaData = 
Mockito.mock(ResultSetMetaData.class);
+        ResultSet resultSet = Mockito.mock(ResultSet.class);
+
+        RecordSchema expectedSchema = useLogicalTypes ? 
givenRecordSchema(columns) : givenRecordSchemaWithOnlyStringType(columns);
+
+        // WHEN
+        setUpMocks(columns, resultSetMetaData, resultSet);
+
+        ResultSetRecordSet testSubject = new ResultSetRecordSet(resultSet, 
recordSchema, 10,0, useLogicalTypes);
+        RecordSchema actualSchema = testSubject.getSchema();
+
+        // THEN
+        thenAllColumnDataTypesAreCorrect(columns, expectedSchema, 
actualSchema);
+    }
+
+    private void setUpMocks(Object[][] columns, ResultSetMetaData 
resultSetMetaData, ResultSet resultSet) throws SQLException {
+        when(resultSet.getMetaData()).thenReturn(resultSetMetaData);
+        when(resultSetMetaData.getColumnCount()).thenReturn(columns.length);
+
+        int indexOfBigDecimal = -1;
+        int index = 0;
+        for (final Object[] column : columns) {
+            when(resultSetMetaData.getColumnLabel((Integer) 
column[0])).thenReturn((String) column[1]);
+            when(resultSetMetaData.getColumnName((Integer) 
column[0])).thenReturn((String) column[1]);
+            when(resultSetMetaData.getColumnType((Integer) 
column[0])).thenReturn((Integer) column[2]);

Review comment:
       Restructuring the mocked columns would help avoid this type casting.

##########
File path: 
nifi-commons/nifi-record/src/test/java/org/apache/nifi/serialization/record/ResultSetRecordSetTest.java
##########
@@ -157,10 +142,31 @@ public void testCreateSchemaWhenOtherType() throws 
SQLException {
         assertEquals(RecordFieldType.DECIMAL.getDecimalDataType(30, 10), 
resultSchema.getField(0).getDataType());
     }
 
+    @Test
+    public void testCreateSchemaWhenOtherTypeAndNoLogicalTypes() throws 
SQLException {
+        // given
+        final List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField("decimal", 
RecordFieldType.DECIMAL.getDecimalDataType(30, 10)));
+        fields.add(new RecordField("date", 
RecordFieldType.DATE.getDataType()));
+        fields.add(new RecordField("time", 
RecordFieldType.TIME.getDataType()));
+        fields.add(new RecordField("timestamp", 
RecordFieldType.TIMESTAMP.getDataType()));
+        final RecordSchema recordSchema = new SimpleRecordSchema(fields);
+        final ResultSet resultSet = givenResultSetForOther(fields);
+
+        // when
+        final ResultSetRecordSet testSubject = new 
ResultSetRecordSet(resultSet, recordSchema, 10, 0, false);
+        final RecordSchema resultSchema = testSubject.getSchema();
+
+        // then
+        assertEquals(RecordFieldType.STRING.getDataType(), 
resultSchema.getField(0).getDataType());

Review comment:
       This checks the type of the first field, but what about the other 
fields? Should all fields be of type `STRING`?  This should also be checked.




-- 
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