SqlHandler { public <K, V> void write(Region<K, V> region, Operation operation, K key, PdxInstance value) throws SQLException { if (value == null && !operation.isDestroy()) { throw new IllegalArgumentException("PdxInstance cannot be null for non-destroy operations"); } try (Connection connection = getConnection()) { EntryColumnData entryColumnData = getEntryColumnData(tableMetaData, key, value, operation); int updateCount = 0; SQLException firstSqlEx = null; try (PreparedStatement statement = getPreparedStatement(connection, tableMetaData, entryColumnData, operation)) { updateCount = executeWriteStatement(statement, entryColumnData, operation); } catch (SQLException e) { if (operation.isDestroy()) { throw e; } firstSqlEx = e; } if (operation.isDestroy()) { return; } if (updateCount <= 0) { Operation upsertOp = getOppositeOperation(operation); try (PreparedStatement upsertStatement = getPreparedStatement(connection, tableMetaData, entryColumnData, upsertOp)) { updateCount = executeWriteStatement(upsertStatement, entryColumnData, operation); } } if (updateCount <= 0 && firstSqlEx != null) { throw firstSqlEx; } assert updateCount == 1 : "expected 1 but updateCount was: " + updateCount; } } SqlHandler(InternalCache cache, String regionName,
      TableMetaDataManager tableMetaDataManager, JdbcConnectorService configService,
      DataSourceFactory dataSourceFactory);  SqlHandler(InternalCache cache, String regionName,
      TableMetaDataManager tableMetaDataManager, JdbcConnectorService configService); PdxInstance read(Region<K, V> region, K key); void write(Region<K, V> region, Operation operation, K key, PdxInstance value);  }
@Test public void whenInsertFailsUpdateSucceeds() throws Exception { when(statement.executeUpdate()).thenReturn(0); PreparedStatement updateStatement = mock(PreparedStatement.class); when(updateStatement.executeUpdate()).thenReturn(1); when(connection.prepareStatement(any())).thenReturn(statement).thenReturn(updateStatement); when(value.getFieldNames()).thenReturn(Collections.emptyList()); handler.write(region, Operation.CREATE, new Object(), value); verify(statement).executeUpdate(); verify(updateStatement).executeUpdate(); verify(statement).close(); verify(updateStatement).close(); }
@Test public void whenUpdateFailsInsertSucceeds() throws Exception { when(statement.executeUpdate()).thenReturn(0); PreparedStatement insertStatement = mock(PreparedStatement.class); when(insertStatement.executeUpdate()).thenReturn(1); when(connection.prepareStatement(any())).thenReturn(statement).thenReturn(insertStatement); when(value.getFieldNames()).thenReturn(Collections.emptyList()); Object putKey = "putKey"; handler.write(region, Operation.UPDATE, putKey, value); verify(statement).executeUpdate(); verify(insertStatement).executeUpdate(); verify(statement).executeUpdate(); verify(statement).setObject(1, putKey); verify(statement).close(); verify(statement).executeUpdate(); verify(statement).setObject(1, putKey); verify(insertStatement).close(); }
@Test public void whenInsertFailsWithExceptionUpdateSucceeds() throws Exception { when(statement.executeUpdate()).thenThrow(SQLException.class); PreparedStatement updateStatement = mock(PreparedStatement.class); when(updateStatement.executeUpdate()).thenReturn(1); when(connection.prepareStatement(any())).thenReturn(statement).thenReturn(updateStatement); when(value.getFieldNames()).thenReturn(Collections.emptyList()); handler.write(region, Operation.CREATE, new Object(), value); verify(statement).executeUpdate(); verify(updateStatement).executeUpdate(); verify(statement).close(); verify(updateStatement).close(); }
@Test public void whenUpdateFailsWithExceptionInsertSucceeds() throws Exception { when(statement.executeUpdate()).thenThrow(SQLException.class); PreparedStatement insertStatement = mock(PreparedStatement.class); when(insertStatement.executeUpdate()).thenReturn(1); when(connection.prepareStatement(any())).thenReturn(statement).thenReturn(insertStatement); when(value.getFieldNames()).thenReturn(Collections.emptyList()); handler.write(region, Operation.UPDATE, new Object(), value); verify(statement).executeUpdate(); verify(insertStatement).executeUpdate(); verify(statement).close(); verify(insertStatement).close(); }
@Test public void whenBothInsertAndUpdateFailExceptionIsThrown() throws Exception { when(statement.executeUpdate()).thenThrow(SQLException.class); PreparedStatement insertStatement = mock(PreparedStatement.class); when(insertStatement.executeUpdate()).thenThrow(SQLException.class); when(connection.prepareStatement(any())).thenReturn(statement).thenReturn(insertStatement); when(value.getFieldNames()).thenReturn(Collections.emptyList()); assertThatThrownBy(() -> handler.write(region, Operation.UPDATE, new Object(), value)) .isInstanceOf(SQLException.class); verify(statement).close(); verify(insertStatement).close(); }
@Test public void whenInsertFailsWithExceptionAndNonUpdateFirstExceptionIsThrown() throws Exception { when(statement.executeUpdate()).thenThrow(SQLException.class); PreparedStatement updateStatement = mock(PreparedStatement.class); when(updateStatement.executeUpdate()).thenReturn(0); when(connection.prepareStatement(any())).thenReturn(statement).thenReturn(updateStatement); when(value.getFieldNames()).thenReturn(Collections.emptyList()); assertThatThrownBy(() -> handler.write(region, Operation.CREATE, new Object(), value)) .isInstanceOf(SQLException.class); verify(statement).close(); verify(updateStatement).close(); }
@Test public void writeThrowsExceptionIfValueIsNullAndNotDoingDestroy() { assertThatThrownBy(() -> handler.write(region, Operation.UPDATE, new Object(), null)) .isInstanceOf(IllegalArgumentException.class); }
@Test public void writeWithCharField() throws Exception { Object fieldValue = 'S'; when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, fieldValue.toString()); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithDateField() throws Exception { Object fieldValue = new Date(); when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(JDBCType.NULL); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, fieldValue); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithDateFieldWithDateTypeFromMetaData() throws Exception { Date fieldValue = new Date(); Object expectedValueWritten = new java.sql.Date(fieldValue.getTime()); JDBCType dataType = JDBCType.DATE; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, expectedValueWritten); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithDateFieldWithTimeTypeFromMetaData() throws Exception { Date fieldValue = new Date(); Object expectedValueWritten = new java.sql.Time(fieldValue.getTime()); JDBCType dataType = JDBCType.TIME; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, expectedValueWritten); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithDateFieldWithTimeWithTimezoneTypeFromMetaData() throws Exception { Date fieldValue = new Date(); Object expectedValueWritten = new java.sql.Time(fieldValue.getTime()); JDBCType dataType = JDBCType.TIME_WITH_TIMEZONE; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, expectedValueWritten); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithDateFieldWithTimestampTypeFromMetaData() throws Exception { Date fieldValue = new Date(); Object expectedValueWritten = new java.sql.Timestamp(fieldValue.getTime()); JDBCType dataType = JDBCType.TIMESTAMP; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, expectedValueWritten); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithDateFieldWithTimestampWithTimezoneTypeFromMetaData() throws Exception { Date fieldValue = new Date(); Object expectedValueWritten = new java.sql.Timestamp(fieldValue.getTime()); JDBCType dataType = JDBCType.TIMESTAMP_WITH_TIMEZONE; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, expectedValueWritten); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithNonCharField() throws Exception { int fieldValue = 100; when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, fieldValue); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithNullField() throws Exception { Object fieldValue = null; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(JDBCType.NULL); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setNull(1, JDBCType.NULL.getVendorTypeNumber()); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void writeWithNullFieldWithDataTypeFromMetaData() throws Exception { Object fieldValue = null; JDBCType dataType = JDBCType.VARCHAR; when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType); when(value.getField(fieldName)).thenReturn(fieldValue); when(statement.executeUpdate()).thenReturn(1); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setNull(1, dataType.getVendorTypeNumber()); verify(statement).setObject(2, createKey); verify(statement).close(); }
@Test public void insertActionSucceeds() throws Exception { when(statement.executeUpdate()).thenReturn(1); when(value.getFieldNames()).thenReturn(Collections.emptyList()); Object createKey = "createKey"; handler.write(region, Operation.CREATE, createKey, value); verify(statement).setObject(1, createKey); verify(statement).executeUpdate(); verify(statement).close(); }
@Test public void insertActionSucceedsWithCompositeKey() throws Exception { when(statement.executeUpdate()).thenReturn(1); Object compositeKeyFieldValueOne = "fieldValueOne"; Object compositeKeyFieldValueTwo = "fieldValueTwo"; PdxInstance compositeKey = mock(PdxInstance.class); when(compositeKey.isDeserializable()).thenReturn(false); when(compositeKey.getFieldNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); when(compositeKey.getField("fieldOne")).thenReturn(compositeKeyFieldValueOne); when(compositeKey.getField("fieldTwo")).thenReturn(compositeKeyFieldValueTwo); when(tableMetaDataView.getKeyColumnNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); FieldMapping fieldMapping1 = mock(FieldMapping.class); when(fieldMapping1.getJdbcName()).thenReturn("fieldOne"); when(fieldMapping1.getPdxName()).thenReturn("fieldOne"); when(fieldMapping1.getJdbcType()).thenReturn(JDBCType.VARCHAR.getName()); FieldMapping fieldMapping2 = mock(FieldMapping.class); when(fieldMapping2.getJdbcName()).thenReturn("fieldTwo"); when(fieldMapping2.getPdxName()).thenReturn("fieldTwo"); when(fieldMapping2.getJdbcType()).thenReturn(JDBCType.VARCHAR.getName()); columnNames.clear(); columnNames.add("fieldOne"); columnNames.add("fieldTwo"); when(tableMetaDataView.getColumnDataType("fieldOne")).thenReturn(JDBCType.VARCHAR); when(tableMetaDataView.getColumnDataType("fieldTwo")).thenReturn(JDBCType.VARCHAR); when(regionMapping.getFieldMappings()).thenReturn(Arrays.asList(fieldMapping1, fieldMapping2)); when(value.getFieldNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); when(regionMapping.getIds()).thenReturn("fieldOne,fieldTwo"); createSqlHandler(); handler.write(region, Operation.CREATE, compositeKey, value); verify(statement).setObject(1, compositeKeyFieldValueOne); verify(statement).setObject(2, compositeKeyFieldValueTwo); verify(statement, times(2)).setObject(anyInt(), any()); verify(statement).executeUpdate(); verify(statement).close(); }
@Test public void updateActionSucceeds() throws Exception { when(statement.executeUpdate()).thenReturn(1); Object updateKey = "updateKey"; when(value.getFieldNames()).thenReturn(Collections.emptyList()); handler.write(region, Operation.UPDATE, updateKey, value); verify(statement).setObject(1, updateKey); verify(statement).executeUpdate(); verify(statement).close(); }
@Test public void updateActionSucceedsWithCompositeKey() throws Exception { when(statement.executeUpdate()).thenReturn(1); Object compositeKeyFieldValueOne = "fieldValueOne"; Object compositeKeyFieldValueTwo = "fieldValueTwo"; PdxInstance compositeKey = mock(PdxInstance.class); when(compositeKey.isDeserializable()).thenReturn(false); when(compositeKey.getFieldNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); when(compositeKey.getField("fieldOne")).thenReturn(compositeKeyFieldValueOne); when(compositeKey.getField("fieldTwo")).thenReturn(compositeKeyFieldValueTwo); when(tableMetaDataView.getKeyColumnNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); FieldMapping fieldMapping1 = mock(FieldMapping.class); when(fieldMapping1.getJdbcName()).thenReturn("fieldOne"); when(fieldMapping1.getPdxName()).thenReturn("fieldOne"); when(fieldMapping1.getJdbcType()).thenReturn(JDBCType.VARCHAR.getName()); FieldMapping fieldMapping2 = mock(FieldMapping.class); when(fieldMapping2.getJdbcName()).thenReturn("fieldTwo"); when(fieldMapping2.getPdxName()).thenReturn("fieldTwo"); when(fieldMapping2.getJdbcType()).thenReturn(JDBCType.VARCHAR.getName()); when(regionMapping.getFieldMappings()).thenReturn(Arrays.asList(fieldMapping1, fieldMapping2)); when(value.getFieldNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); columnNames.clear(); columnNames.add("fieldOne"); columnNames.add("fieldTwo"); when(tableMetaDataView.getColumnDataType("fieldOne")).thenReturn(JDBCType.VARCHAR); when(tableMetaDataView.getColumnDataType("fieldTwo")).thenReturn(JDBCType.VARCHAR); when(regionMapping.getIds()).thenReturn("fieldOne,fieldTwo"); createSqlHandler(); handler.write(region, Operation.UPDATE, compositeKey, value); verify(statement).setObject(1, compositeKeyFieldValueOne); verify(statement).setObject(2, compositeKeyFieldValueTwo); verify(statement, times(2)).setObject(anyInt(), any()); verify(statement).executeUpdate(); verify(statement).close(); }
@Test public void destroyActionSucceeds() throws Exception { when(statement.executeUpdate()).thenReturn(1); Object destroyKey = "destroyKey"; handler.write(region, Operation.DESTROY, destroyKey, value); verify(statement).setObject(1, destroyKey); verify(statement, times(1)).setObject(anyInt(), any()); verify(statement).close(); }
@Test public void destroyActionSucceedsWithCompositeKey() throws Exception { when(statement.executeUpdate()).thenReturn(1); Object destroyKeyFieldValueOne = "fieldValueOne"; Object destroyKeyFieldValueTwo = "fieldValueTwo"; PdxInstance destroyKey = mock(PdxInstance.class); when(destroyKey.isDeserializable()).thenReturn(false); when(destroyKey.getFieldNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); when(destroyKey.getField("fieldOne")).thenReturn(destroyKeyFieldValueOne); when(destroyKey.getField("fieldTwo")).thenReturn(destroyKeyFieldValueTwo); when(tableMetaDataView.getKeyColumnNames()).thenReturn(Arrays.asList("fieldOne", "fieldTwo")); FieldMapping fieldMapping1 = mock(FieldMapping.class); when(fieldMapping1.getJdbcName()).thenReturn("fieldOne"); when(fieldMapping1.getPdxName()).thenReturn("fieldOne"); when(fieldMapping1.getJdbcType()).thenReturn(JDBCType.VARCHAR.getName()); FieldMapping fieldMapping2 = mock(FieldMapping.class); when(fieldMapping2.getJdbcName()).thenReturn("fieldTwo"); when(fieldMapping2.getPdxName()).thenReturn("fieldTwo"); when(fieldMapping2.getJdbcType()).thenReturn(JDBCType.VARCHAR.getName()); columnNames.clear(); columnNames.add("fieldOne"); columnNames.add("fieldTwo"); when(tableMetaDataView.getColumnDataType("fieldOne")).thenReturn(JDBCType.VARCHAR); when(tableMetaDataView.getColumnDataType("fieldTwo")).thenReturn(JDBCType.VARCHAR); when(regionMapping.getFieldMappings()).thenReturn(Arrays.asList(fieldMapping1, fieldMapping2)); when(regionMapping.getIds()).thenReturn("fieldOne,fieldTwo"); createSqlHandler(); handler.write(region, Operation.DESTROY, destroyKey, value); verify(statement).setObject(1, destroyKeyFieldValueOne); verify(statement).setObject(2, destroyKeyFieldValueTwo); verify(statement, times(2)).setObject(anyInt(), any()); verify(statement).close(); }
@Test public void destroyActionThatRemovesNoRowCompletesUnexceptionally() throws Exception { when(statement.executeUpdate()).thenReturn(0); Object destroyKey = "destroyKey"; handler.write(region, Operation.DESTROY, destroyKey, value); verify(statement).setObject(1, destroyKey); verify(statement, times(1)).setObject(anyInt(), any()); verify(statement).close(); }
@Test public void destroyThrowExceptionWhenFail() throws Exception { when(statement.executeUpdate()).thenThrow(SQLException.class); assertThatThrownBy(() -> handler.write(region, Operation.DESTROY, new Object(), value)) .isInstanceOf(SQLException.class); }
@Test public void writesWithUnsupportedOperationThrows() throws Exception { assertThatThrownBy(() -> handler.write(region, Operation.INVALIDATE, new Object(), value)) .isInstanceOf(InternalGemFireException.class); }
@Test public void preparedStatementClearedAfterExecution() throws Exception { when(statement.executeUpdate()).thenReturn(1); when(value.getFieldNames()).thenReturn(Collections.emptyList()); handler.write(region, Operation.CREATE, new Object(), value); verify(statement).close(); }