You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2018/04/03 17:38:28 UTC

[geode] branch develop updated: GEODE-4872: handle Blob when reading from JDBC (#1692)

This is an automated email from the ASF dual-hosted git repository.

dschneider pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 7070fc9  GEODE-4872: handle Blob when reading from JDBC (#1692)
7070fc9 is described below

commit 7070fc936c274556f040861eed037d1a24dc3706
Author: Darrel Schneider <ds...@pivotal.io>
AuthorDate: Tue Apr 3 10:38:25 2018 -0700

    GEODE-4872: handle Blob when reading from JDBC (#1692)
    
    When a pdx BYTE_ARRAY or OBJECT field is read and
    the column type is BLOB, getBlob is called and
    its value is converted to a byte[].
---
 .../jdbc/internal/SqlToPdxInstanceCreator.java     | 127 +++++++++-----
 .../jdbc/internal/SqlToPdxInstanceCreatorTest.java | 190 ++++++++++++++++++---
 2 files changed, 244 insertions(+), 73 deletions(-)

diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java
index 6d08e0b..5b04755 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java
@@ -14,6 +14,7 @@
  */
 package org.apache.geode.connectors.jdbc.internal;
 
+import java.sql.Blob;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
@@ -33,6 +34,7 @@ class SqlToPdxInstanceCreator {
   private final RegionMapping regionMapping;
   private final ResultSet resultSet;
   private final TableMetaDataView tableMetaData;
+  private final PdxInstanceFactory factory;
 
   public SqlToPdxInstanceCreator(InternalCache cache, RegionMapping regionMapping,
       ResultSet resultSet, TableMetaDataView tableMetaData) {
@@ -40,51 +42,46 @@ class SqlToPdxInstanceCreator {
     this.regionMapping = regionMapping;
     this.resultSet = resultSet;
     this.tableMetaData = tableMetaData;
+    this.factory = createPdxInstanceFactory();
   }
 
   public PdxInstance create() throws SQLException {
-    PdxInstanceFactory factory = getPdxInstanceFactory(cache, regionMapping);
-    PdxInstance pdxInstance = null;
-    if (resultSet.next()) {
-      ResultSetMetaData metaData = resultSet.getMetaData();
-      int ColumnsNumber = metaData.getColumnCount();
-      TypeRegistry typeRegistry = cache.getPdxRegistry();
-      for (int i = 1; i <= ColumnsNumber; i++) {
-        String columnName = metaData.getColumnName(i);
-        if (regionMapping.isPrimaryKeyInValue()
-            || !tableMetaData.getKeyColumnName().equalsIgnoreCase(columnName)) {
-          String fieldName = regionMapping.getFieldNameForColumn(columnName, typeRegistry);
-          FieldType fieldType =
-              getFieldType(typeRegistry, regionMapping.getPdxClassName(), fieldName);
-          writeField(factory, resultSet, i, fieldName, fieldType, columnName);
-        }
-      }
-      if (resultSet.next()) {
-        throw new JdbcConnectorException(
-            "Multiple rows returned for query: " + resultSet.getStatement().toString());
+    if (!resultSet.next()) {
+      return null;
+    }
+    TypeRegistry typeRegistry = cache.getPdxRegistry();
+    ResultSetMetaData metaData = resultSet.getMetaData();
+    final int columnCount = metaData.getColumnCount();
+    for (int i = 1; i <= columnCount; i++) {
+      String columnName = metaData.getColumnName(i);
+      if (regionMapping.isPrimaryKeyInValue()
+          || !tableMetaData.getKeyColumnName().equalsIgnoreCase(columnName)) {
+        String fieldName = regionMapping.getFieldNameForColumn(columnName, typeRegistry);
+        FieldType fieldType = getFieldType(typeRegistry, fieldName);
+        writeField(columnName, i, fieldName, fieldType);
       }
-      pdxInstance = factory.create();
     }
-    return pdxInstance;
+    if (resultSet.next()) {
+      throw new JdbcConnectorException(
+          "Multiple rows returned for query: " + resultSet.getStatement());
+    }
+    return factory.create();
   }
 
-  private PdxInstanceFactory getPdxInstanceFactory(InternalCache cache,
-      RegionMapping regionMapping) {
+  private PdxInstanceFactory createPdxInstanceFactory() {
     String valueClassName = regionMapping.getPdxClassName();
-    PdxInstanceFactory factory;
     if (valueClassName != null) {
-      factory = cache.createPdxInstanceFactory(valueClassName);
+      return cache.createPdxInstanceFactory(valueClassName);
     } else {
-      factory = cache.createPdxInstanceFactory("no class", false);
+      return cache.createPdxInstanceFactory("no class", false);
     }
-    return factory;
   }
 
   /**
    * @throws SQLException if the column value get fails
    */
-  private void writeField(PdxInstanceFactory factory, ResultSet resultSet, int columnIndex,
-      String fieldName, FieldType fieldType, String columnName) throws SQLException {
+  private void writeField(String columnName, int columnIndex, String fieldName, FieldType fieldType)
+      throws SQLException {
     switch (fieldType) {
       case STRING:
         factory.writeString(fieldName, resultSet.getString(columnIndex));
@@ -141,7 +138,13 @@ class SqlToPdxInstanceCreator {
         break;
       }
       case BYTE_ARRAY:
-        factory.writeByteArray(fieldName, resultSet.getBytes(columnIndex));
+        byte[] byteData;
+        if (isBlobColumn(columnName)) {
+          byteData = getBlobData(columnIndex);
+        } else {
+          byteData = resultSet.getBytes(columnIndex);
+        }
+        factory.writeByteArray(fieldName, byteData);
         break;
       case BOOLEAN_ARRAY:
         factory.writeBooleanArray(fieldName,
@@ -183,22 +186,55 @@ class SqlToPdxInstanceCreator {
         factory.writeArrayOfByteArrays(fieldName,
             convertJdbcObjectToJavaType(byte[][].class, resultSet.getObject(columnIndex)));
         break;
-      case OBJECT:
-        Object v = resultSet.getObject(columnIndex);
-        if (v instanceof java.util.Date) {
-          if (v instanceof java.sql.Date) {
-            java.sql.Date sqlDate = (java.sql.Date) v;
-            v = new java.util.Date(sqlDate.getTime());
-          } else if (v instanceof java.sql.Time) {
-            java.sql.Time sqlTime = (java.sql.Time) v;
-            v = new java.util.Date(sqlTime.getTime());
-          } else if (v instanceof java.sql.Timestamp) {
-            java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp) v;
-            v = new java.util.Date(sqlTimestamp.getTime());
+      case OBJECT: {
+        Object v;
+        if (isBlobColumn(columnName)) {
+          v = getBlobData(columnIndex);
+        } else {
+          v = resultSet.getObject(columnIndex);
+          if (v instanceof java.util.Date) {
+            if (v instanceof java.sql.Date) {
+              java.sql.Date sqlDate = (java.sql.Date) v;
+              v = new java.util.Date(sqlDate.getTime());
+            } else if (v instanceof java.sql.Time) {
+              java.sql.Time sqlTime = (java.sql.Time) v;
+              v = new java.util.Date(sqlTime.getTime());
+            } else if (v instanceof java.sql.Timestamp) {
+              java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp) v;
+              v = new java.util.Date(sqlTimestamp.getTime());
+            }
           }
         }
         factory.writeObject(fieldName, v);
         break;
+      }
+    }
+  }
+
+  private boolean isBlobColumn(String columnName) throws SQLException {
+    return this.tableMetaData.getColumnDataType(columnName) == Types.BLOB;
+  }
+
+  /**
+   * If the given column contains a Blob returns its data as a byte array;
+   * otherwise return null.
+   *
+   * @throws JdbcConnectorException if blob is too big to fit in a byte array
+   */
+  private byte[] getBlobData(int columnIndex) throws SQLException {
+    Blob blob = resultSet.getBlob(columnIndex);
+    if (blob == null) {
+      return null;
+    }
+    try {
+      long blobLength = blob.length();
+      if (blobLength > Integer.MAX_VALUE) {
+        throw new JdbcConnectorException(
+            "Blob of length " + blobLength + " is too big to be converted to a byte array.");
+      }
+      return blob.getBytes(1, (int) blobLength);
+    } finally {
+      blob.free();
     }
   }
 
@@ -212,11 +248,11 @@ class SqlToPdxInstanceCreator {
     }
   }
 
-  private FieldType getFieldType(TypeRegistry typeRegistry, String pdxClassName, String fieldName) {
+  private FieldType getFieldType(TypeRegistry typeRegistry, String fieldName) {
+    String pdxClassName = regionMapping.getPdxClassName();
     if (pdxClassName == null) {
       return FieldType.OBJECT;
     }
-
     PdxType pdxType = typeRegistry.getPdxTypeForField(fieldName, pdxClassName);
     if (pdxType != null) {
       PdxField pdxField = pdxType.getPdxField(fieldName);
@@ -224,10 +260,7 @@ class SqlToPdxInstanceCreator {
         return pdxField.getFieldType();
       }
     }
-
     throw new JdbcConnectorException("Could not find PdxType for field " + fieldName
         + ". Add class " + pdxClassName + " with " + fieldName + " to pdx registry.");
-
   }
-
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java
index 9f84f72..d9b5250 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import java.sql.Blob;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
@@ -64,7 +65,6 @@ public class SqlToPdxInstanceCreatorTest {
   private static final String PDX_FIELD_NAME_2 = COLUMN_NAME_2.toLowerCase();
 
   private InternalCache cache;
-  private SqlToPdxInstanceCreator sqlToPdxInstanceCreator;
   private RegionMapping regionMapping;
   private ResultSet resultSet;
   private TableMetaDataView tableMetaDataView;
@@ -79,8 +79,6 @@ public class SqlToPdxInstanceCreatorTest {
     resultSet = mock(ResultSet.class);
     tableMetaDataView = mock(TableMetaDataView.class);
     when(tableMetaDataView.getKeyColumnName()).thenReturn(KEY_COLUMN);
-    sqlToPdxInstanceCreator =
-        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, tableMetaDataView);
   }
 
   @Test
@@ -89,7 +87,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getPdxClassName()).thenReturn(pdxClassName);
     when(resultSet.next()).thenReturn(false);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verify(cache).createPdxInstanceFactory(pdxClassName);
     verifyNoMoreInteractions(cache);
@@ -99,7 +97,7 @@ public class SqlToPdxInstanceCreatorTest {
   public void usesPdxFactoryForNoPdxClassWhenClassNonExistent() throws Exception {
     when(resultSet.next()).thenReturn(false);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verify(cache).createPdxInstanceFactory("no class", false);
     verifyNoMoreInteractions(cache);
@@ -108,7 +106,9 @@ public class SqlToPdxInstanceCreatorTest {
   @Test
   public void readReturnsNullIfNoResultsReturned() throws Exception {
     when(resultSet.next()).thenReturn(false);
-    PdxInstance pdxInstance = sqlToPdxInstanceCreator.create();
+
+    PdxInstance pdxInstance = createPdxInstance();
+
     assertThat(pdxInstance).isNull();
   }
 
@@ -118,14 +118,15 @@ public class SqlToPdxInstanceCreatorTest {
     when(resultSet.next()).thenReturn(true).thenReturn(false);
     PdxInstanceFactory factory = mock(PdxInstanceFactory.class);
     when(cache.createPdxInstanceFactory(anyString(), anyBoolean())).thenReturn(factory);
+    when(regionMapping.isPrimaryKeyInValue()).thenReturn(false);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_2), any()))
         .thenReturn(PDX_FIELD_NAME_2);
     tableMetaDataView = mock(TableMetaDataView.class);
     when(tableMetaDataView.getKeyColumnName()).thenReturn(COLUMN_NAME_1);
-    sqlToPdxInstanceCreator =
-        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, tableMetaDataView);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verify(factory).writeObject(PDX_FIELD_NAME_2, COLUMN_VALUE_2);
     verify(factory, times(1)).writeObject(any(), any());
@@ -133,6 +134,27 @@ public class SqlToPdxInstanceCreatorTest {
   }
 
   @Test
+  public void readResultIncludesKeyColumnIfPrimaryKeyInValue() throws Exception {
+    setupResultSetForTwoObjectColumns(resultSet);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = mock(PdxInstanceFactory.class);
+    when(cache.createPdxInstanceFactory(anyString(), anyBoolean())).thenReturn(factory);
+    when(regionMapping.isPrimaryKeyInValue()).thenReturn(true);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_2), any()))
+        .thenReturn(PDX_FIELD_NAME_2);
+    tableMetaDataView = mock(TableMetaDataView.class);
+    when(tableMetaDataView.getKeyColumnName()).thenReturn(COLUMN_NAME_1);
+
+    createPdxInstance();
+
+    verify(factory).writeObject(PDX_FIELD_NAME_1, COLUMN_VALUE_1);
+    verify(factory).writeObject(PDX_FIELD_NAME_2, COLUMN_VALUE_2);
+    verify(factory).create();
+  }
+
+  @Test
   public void readReturnsDataFromAllResultColumns() throws Exception {
     setupResultSetForTwoObjectColumns(resultSet);
     when(resultSet.next()).thenReturn(true).thenReturn(false);
@@ -143,7 +165,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_2), any()))
         .thenReturn(PDX_FIELD_NAME_2);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verify(factory).writeObject(PDX_FIELD_NAME_1, COLUMN_VALUE_1);
     verify(factory).writeObject(PDX_FIELD_NAME_2, COLUMN_VALUE_2);
@@ -159,7 +181,7 @@ public class SqlToPdxInstanceCreatorTest {
     String fieldName1 = "pdxFieldName1";
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any())).thenReturn(fieldName1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verify(factory).writeObject(fieldName1, COLUMN_VALUE_1);
     verify(factory).create();
@@ -174,12 +196,18 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType);
     verify(factory).create();
   }
 
+  private PdxInstance createPdxInstance() throws SQLException {
+    SqlToPdxInstanceCreator sqlToPdxInstanceCreator =
+        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, tableMetaDataView);
+    return sqlToPdxInstanceCreator.create();
+  }
+
   @Test
   @Parameters(source = FieldType.class)
   public void readOfNullWritesFieldGivenPdxFieldType(FieldType fieldType) throws Exception {
@@ -189,7 +217,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, null);
     verify(factory).create();
@@ -209,7 +237,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -231,7 +259,98 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfByteArrayFieldWithBlob() throws Exception {
+    FieldType fieldType = FieldType.BYTE_ARRAY;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.BLOB);
+    byte[] expectedValue = new byte[] {1, 2, 3};
+    Blob blob = mock(Blob.class);
+    when(blob.length()).thenReturn((long) expectedValue.length);
+    when(blob.getBytes(1, expectedValue.length)).thenReturn(expectedValue);
+    when(resultSet.getBlob(1)).thenReturn(blob);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    createPdxInstance();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfByteArrayFieldWithNullBlob() throws Exception {
+    FieldType fieldType = FieldType.BYTE_ARRAY;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.BLOB);
+    byte[] expectedValue = null;
+    Blob blob = null;
+    when(resultSet.getBlob(1)).thenReturn(blob);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    createPdxInstance();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfByteArrayFieldWithHugeBlobThrows() throws Exception {
+    FieldType fieldType = FieldType.BYTE_ARRAY;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.BLOB);
+    Blob blob = mock(Blob.class);
+    when(blob.length()).thenReturn((long) Integer.MAX_VALUE + 1);
+    when(resultSet.getBlob(1)).thenReturn(blob);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+    thrown.expect(JdbcConnectorException.class);
+    thrown.expectMessage("Blob of length 2147483648 is too big to be converted to a byte array.");
+
+    createPdxInstance();
+  }
+
+  @Test
+  public void readOfObjectFieldWithBlob() throws Exception {
+    FieldType fieldType = FieldType.OBJECT;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.BLOB);
+    byte[] expectedValue = new byte[] {1, 2, 3};
+    Blob blob = mock(Blob.class);
+    when(blob.length()).thenReturn((long) expectedValue.length);
+    when(blob.getBytes(1, expectedValue.length)).thenReturn(expectedValue);
+    when(resultSet.getBlob(1)).thenReturn(blob);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -253,7 +372,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -275,7 +394,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -296,7 +415,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -316,7 +435,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -337,7 +456,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -358,7 +477,7 @@ public class SqlToPdxInstanceCreatorTest {
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
 
-    sqlToPdxInstanceCreator.create();
+    createPdxInstance();
 
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
@@ -376,10 +495,10 @@ public class SqlToPdxInstanceCreatorTest {
         .thenReturn(PDX_FIELD_NAME_1);
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_2), any()))
         .thenReturn(PDX_FIELD_NAME_2);
-
     thrown.expect(JdbcConnectorException.class);
     thrown.expectMessage("Could not convert ");
-    sqlToPdxInstanceCreator.create();
+
+    createPdxInstance();
   }
 
   @Test
@@ -389,9 +508,9 @@ public class SqlToPdxInstanceCreatorTest {
     when(resultSet.getStatement()).thenReturn(mock(PreparedStatement.class));
     when(cache.createPdxInstanceFactory(anyString(), anyBoolean()))
         .thenReturn(mock(PdxInstanceFactory.class));
-
     thrown.expect(JdbcConnectorException.class);
-    sqlToPdxInstanceCreator.create();
+
+    createPdxInstance();
   }
 
   @Test
@@ -409,10 +528,29 @@ public class SqlToPdxInstanceCreatorTest {
     when(pdxType.getPdxField(PDX_FIELD_NAME_1)).thenReturn(null);
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
         .thenReturn(PDX_FIELD_NAME_1);
+    thrown.expect(JdbcConnectorException.class);
+    thrown.expectMessage("Could not find PdxType");
+
+    createPdxInstance();
+  }
 
+  @Test
+  public void readThrowsWithMissingPdxType() throws Exception {
+    setupResultSet(resultSet, FieldType.OBJECT);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = mock(PdxInstanceFactory.class);
+    String pdxClassName = "myPdxClassName";
+    when(cache.createPdxInstanceFactory(pdxClassName)).thenReturn(factory);
+    TypeRegistry pdxTypeRegistry = mock(TypeRegistry.class);
+    when(cache.getPdxRegistry()).thenReturn(pdxTypeRegistry);
+    when(regionMapping.getPdxClassName()).thenReturn(pdxClassName);
+    when(pdxTypeRegistry.getPdxTypeForField(PDX_FIELD_NAME_1, pdxClassName)).thenReturn(null);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
     thrown.expect(JdbcConnectorException.class);
     thrown.expectMessage("Could not find PdxType");
-    sqlToPdxInstanceCreator.create();
+
+    createPdxInstance();
   }
 
   private void setupResultSetForTwoObjectColumns(ResultSet result) throws SQLException {

-- 
To stop receiving notification emails like this one, please contact
dschneider@apache.org.