Skip to content

Commit 67035b9

Browse files
committed
PDI-19719 - Fixed NPE when pgCopyOut is closing
1 parent 123cb2c commit 67035b9

File tree

2 files changed

+59
-37
lines changed

2 files changed

+59
-37
lines changed

plugins/postgresql-db-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/pgbulkloader/PGBulkLoader.java

+13-18
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* Pentaho Data Integration
44
*
5-
* Copyright (C) 2002-2022 by Hitachi Vantara : http://www.pentaho.com
5+
* Copyright (C) 2002-2023 by Hitachi Vantara : http://www.pentaho.com
66
*
77
*******************************************************************************
88
*
@@ -30,22 +30,16 @@
3030
//
3131
//
3232

33-
import java.io.IOException;
34-
import java.math.BigDecimal;
35-
import java.nio.charset.Charset;
36-
import java.sql.Connection;
37-
import java.sql.ResultSet;
38-
import java.sql.SQLException;
39-
import java.sql.Statement;
40-
33+
import com.google.common.annotations.VisibleForTesting;
34+
import org.apache.commons.io.IOUtils;
4135
import org.pentaho.di.core.Const;
42-
import org.pentaho.di.core.util.Utils;
4336
import org.pentaho.di.core.database.Database;
4437
import org.pentaho.di.core.database.DatabaseMeta;
4538
import org.pentaho.di.core.exception.KettleException;
4639
import org.pentaho.di.core.logging.LoggingObjectInterface;
4740
import org.pentaho.di.core.row.RowMetaInterface;
4841
import org.pentaho.di.core.row.ValueMetaInterface;
42+
import org.pentaho.di.core.util.Utils;
4943
import org.pentaho.di.i18n.BaseMessages;
5044
import org.pentaho.di.trans.Trans;
5145
import org.pentaho.di.trans.TransMeta;
@@ -54,11 +48,15 @@
5448
import org.pentaho.di.trans.step.StepInterface;
5549
import org.pentaho.di.trans.step.StepMeta;
5650
import org.pentaho.di.trans.step.StepMetaInterface;
51+
import org.postgresql.PGConnection;
5752
import org.postgresql.copy.PGCopyOutputStream;
5853

59-
import com.google.common.annotations.VisibleForTesting;
60-
61-
import org.postgresql.PGConnection;
54+
import java.math.BigDecimal;
55+
import java.nio.charset.Charset;
56+
import java.sql.Connection;
57+
import java.sql.ResultSet;
58+
import java.sql.SQLException;
59+
import java.sql.Statement;
6260

6361
/**
6462
* Performs a bulk load to a postgres table.
@@ -492,11 +490,8 @@ public void dispose( StepMetaInterface smi, StepDataInterface sdi ) {
492490
meta = (PGBulkLoaderMeta) smi;
493491
data = (PGBulkLoaderData) sdi;
494492

495-
try {
496-
pgCopyOut.close();
497-
} catch ( IOException e ) {
498-
logError( "Error while closing the Postgres Output Stream", e.getMessage() );
499-
}
493+
IOUtils.closeQuietly( pgCopyOut,
494+
e -> logError( "Error while closing the Postgres Output Stream", e.getMessage() ) );
500495

501496
if ( data.db != null ) {
502497
data.db.close();

plugins/postgresql-db-bulk-loader/impl/src/test/java/org/pentaho/di/trans/steps/pgbulkloader/PGBulkLoaderTest.java

+46-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* Pentaho Data Integration
44
*
5-
* Copyright (C) 2017-2022 by Hitachi Vantara : http://www.pentaho.com
5+
* Copyright (C) 2017-2023 by Hitachi Vantara : http://www.pentaho.com
66
*
77
*******************************************************************************
88
*
@@ -21,20 +21,6 @@
2121
******************************************************************************/
2222
package org.pentaho.di.trans.steps.pgbulkloader;
2323

24-
import static org.hamcrest.core.StringContains.containsString;
25-
import static org.junit.Assert.assertEquals;
26-
import static org.junit.Assert.assertFalse;
27-
import static org.junit.Assert.assertNotNull;
28-
import static org.junit.Assert.assertThat;
29-
import static org.junit.Assert.fail;
30-
import static org.mockito.Matchers.any;
31-
import static org.mockito.Mockito.doNothing;
32-
import static org.mockito.Mockito.doReturn;
33-
import static org.mockito.Mockito.mock;
34-
import static org.mockito.Mockito.spy;
35-
import static org.mockito.Mockito.verify;
36-
import static org.mockito.Mockito.when;
37-
3824
import org.junit.After;
3925
import org.junit.Before;
4026
import org.junit.BeforeClass;
@@ -58,10 +44,20 @@
5844
import java.io.IOException;
5945
import java.lang.reflect.Field;
6046

47+
import static org.hamcrest.core.StringContains.containsString;
6148
import static org.junit.Assert.assertEquals;
49+
import static org.junit.Assert.assertFalse;
6250
import static org.junit.Assert.assertNotNull;
51+
import static org.junit.Assert.assertThat;
52+
import static org.junit.Assert.fail;
6353
import static org.mockito.Matchers.any;
64-
import static org.mockito.Mockito.*;
54+
import static org.mockito.Mockito.doAnswer;
55+
import static org.mockito.Mockito.doNothing;
56+
import static org.mockito.Mockito.doReturn;
57+
import static org.mockito.Mockito.mock;
58+
import static org.mockito.Mockito.spy;
59+
import static org.mockito.Mockito.verify;
60+
import static org.mockito.Mockito.when;
6561
import static org.pentaho.di.core.row.ValueMetaInterface.TYPE_BOOLEAN;
6662

6763
public class PGBulkLoaderTest {
@@ -207,6 +203,37 @@ public void writeBooleanToPgOutput() throws Exception {
207203
assertEquals( "false", "0" + Const.CR, out.toString() );
208204
}
209205

206+
/**
207+
* Regression test for PDI-18989
208+
*/
209+
@Test
210+
public void emptyInput() throws Exception {
211+
final PGBulkLoaderMeta meta = initMeta( "field" );
212+
final PGBulkLoaderData data = initData();
213+
final PGBulkLoader loader = spy( this.pgBulkLoader );
214+
doReturn( null ).when( loader ).getRow();
215+
216+
loader.init( meta, data );
217+
assertFalse( "Step finished", loader.processRow( meta, data ) );
218+
loader.dispose( meta, data );
219+
}
220+
221+
/**
222+
* Step does not have defined any output fields -> initialize of copy command failed.
223+
*/
224+
@Test
225+
public void do_copyFailed() throws Exception {
226+
final PGBulkLoaderMeta meta = initMeta();
227+
final PGBulkLoaderData data = initData();
228+
final PGBulkLoader loader = spy( this.pgBulkLoader );
229+
doReturn( new Object[] { "test data" } ).when( loader ).getRow();
230+
231+
loader.init( meta, data );
232+
assertFalse( "Process row failed", loader.processRow( meta, data ) );
233+
assertEquals( "Step has error", 1, loader.getErrors() );
234+
loader.dispose( meta, data );
235+
}
236+
210237
private ByteArrayOutputStream initPGCopyOutputStream() throws IOException, NoSuchFieldException, IllegalAccessException {
211238
final ByteArrayOutputStream out = new ByteArrayOutputStream();
212239
final PGCopyOutputStream pgCopy = mock( PGCopyOutputStream.class );
@@ -226,10 +253,10 @@ private RowMeta initRowMeta( String valueName, int type ) throws KettlePluginExc
226253
return rowMeta;
227254
}
228255

229-
private PGBulkLoaderMeta initMeta( String valueName ) throws KettleXMLException {
256+
private PGBulkLoaderMeta initMeta( String... valueNames ) throws KettleXMLException {
230257
final PGBulkLoaderMeta meta = getPgBulkLoaderMock( null );
231-
when( meta.getFieldStream() ).thenReturn( new String[] {valueName} );
232-
when( meta.getDateMask() ).thenReturn( new String[] {""} );
258+
when( meta.getFieldStream() ).thenReturn( valueNames );
259+
when( meta.getDateMask() ).thenReturn( new String[] { "" } );
233260
return meta;
234261
}
235262

0 commit comments

Comments
 (0)