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

mattcasters pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new d17034f9c8 Issue #8904: Fix false positive result on error in Action 
Columns Exist (#8911)
d17034f9c8 is described below

commit d17034f9c82a39db00581c0520f0195958c0d58d
Author: Samuel Willyanto <[email protected]>
AuthorDate: Thu Oct 15 14:21:25 2026 +0700

    Issue #8904: Fix false positive result on error in Action Columns Exist 
(#8911)
---
 .../org/apache/hop/core/database/Database.java     |   3 +
 .../org/apache/hop/core/database/DatabaseTest.java |  42 +++++
 .../actions/columnsexist/ActionColumnsExist.java   | 100 +++++-----
 .../columnsexist/ActionColumnsExistDialog.java     | 144 ++++++++++-----
 .../columnsexist/ActionColumnsExistTest.java       | 202 ++++++++++++++++++++-
 5 files changed, 398 insertions(+), 93 deletions(-)

diff --git a/core/src/main/java/org/apache/hop/core/database/Database.java 
b/core/src/main/java/org/apache/hop/core/database/Database.java
index 626a3197e9..4ba3b61483 100644
--- a/core/src/main/java/org/apache/hop/core/database/Database.java
+++ b/core/src/main/java/org/apache/hop/core/database/Database.java
@@ -44,6 +44,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 import lombok.Getter;
@@ -4435,6 +4436,7 @@ public class Database implements IVariables, 
ILoggingObject, AutoCloseable {
       log.logDetailed(CONST_READ + schemaList.size() + " schemas from db 
meta-data.");
     }
 
+    schemaList.removeIf(Objects::isNull);
     schemaList.sort(String.CASE_INSENSITIVE_ORDER);
     return schemaList.toArray(new String[0]);
   }
@@ -4454,6 +4456,7 @@ public class Database implements IVariables, 
ILoggingObject, AutoCloseable {
       log.logDetailed(CONST_READ + catalogList.size() + " catalogs from db 
meta-data.");
     }
 
+    catalogList.removeIf(Objects::isNull);
     catalogList.sort(String.CASE_INSENSITIVE_ORDER);
     return catalogList.toArray(new String[0]);
   }
diff --git a/core/src/test/java/org/apache/hop/core/database/DatabaseTest.java 
b/core/src/test/java/org/apache/hop/core/database/DatabaseTest.java
index fdb08e4ca3..637d9524ca 100644
--- a/core/src/test/java/org/apache/hop/core/database/DatabaseTest.java
+++ b/core/src/test/java/org/apache/hop/core/database/DatabaseTest.java
@@ -1188,4 +1188,46 @@ class DatabaseTest {
     verify(statement).execute();
     verify(statement).close();
   }
+
+  @Test
+  void testGetSchemasFiltersNulls() throws Exception {
+    DatabaseMeta meta = mock(DatabaseMeta.class);
+    DatabaseMetaData dbMetaData = mock(DatabaseMetaData.class);
+    Connection conn = mockConnection(dbMetaData);
+    ResultSet rs = mock(ResultSet.class);
+
+    when(dbMetaData.getSchemas()).thenReturn(rs);
+    when(rs.next()).thenReturn(true, true, true, false);
+    when(rs.getString(1)).thenReturn("schemaB", null, "schemaA");
+
+    Database db = new Database(log, variables, meta);
+    db.setConnection(conn);
+    String[] schemas = db.getSchemas();
+
+    assertNotNull(schemas);
+    assertEquals(2, schemas.length);
+    assertEquals("schemaA", schemas[0]);
+    assertEquals("schemaB", schemas[1]);
+  }
+
+  @Test
+  void testGetCatalogsFiltersNulls() throws Exception {
+    DatabaseMeta meta = mock(DatabaseMeta.class);
+    DatabaseMetaData dbMetaData = mock(DatabaseMetaData.class);
+    Connection conn = mockConnection(dbMetaData);
+    ResultSet rs = mock(ResultSet.class);
+
+    when(dbMetaData.getCatalogs()).thenReturn(rs);
+    when(rs.next()).thenReturn(true, true, true, false);
+    when(rs.getString(1)).thenReturn("catalogB", null, "catalogA");
+
+    Database db = new Database(log, variables, meta);
+    db.setConnection(conn);
+    String[] catalogs = db.getCatalogs();
+
+    assertNotNull(catalogs);
+    assertEquals(2, catalogs.length);
+    assertEquals("catalogA", catalogs[0]);
+    assertEquals("catalogB", catalogs[1]);
+  }
 }
diff --git 
a/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExist.java
 
b/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExist.java
index 1b032bdc78..9e9db32760 100644
--- 
a/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExist.java
+++ 
b/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExist.java
@@ -119,82 +119,96 @@ public class ActionColumnsExist extends ActionBase 
implements Cloneable, IAction
     int nrexistcolums = 0;
     int nrnotexistcolums = 0;
 
-    if (Utils.isEmpty(tableName)) {
+    String realConnection = resolve(connectionName);
+    if (Utils.isEmpty(realConnection)) {
+      logError(BaseMessages.getString(PKG, 
"ActionColumnsExist.Error.NoDbConnection"));
+      return result;
+    }
+
+    DatabaseMeta databaseMeta = null;
+    if (parentWorkflowMeta != null) {
+      databaseMeta = parentWorkflowMeta.findDatabase(realConnection, 
getVariables());
+    }
+    if (databaseMeta == null) {
+      logError(BaseMessages.getString(PKG, 
"ActionColumnsExist.Error.NoDbConnection"));
+      return result;
+    }
+
+    String realTableName = resolve(tableName);
+    if (Utils.isEmpty(realTableName)) {
       logError(BaseMessages.getString(PKG, 
"ActionColumnsExist.Error.TablenameEmpty"));
       return result;
     }
-    if (columns == null) {
+    if (columns == null || columns.isEmpty()) {
       logError(BaseMessages.getString(PKG, 
"ActionColumnsExist.Error.ColumnameEmpty"));
       return result;
     }
 
-    DatabaseMeta databaseMeta = 
parentWorkflowMeta.findDatabase(connectionName, getVariables());
-    if (databaseMeta != null) {
-      try (Database db = new Database(this, this, databaseMeta)) {
-        String realSchemaName = resolve(schemaName);
-        String realTableName = resolve(tableName);
+    try (Database db = getDatabase(databaseMeta)) {
+      db.connect();
+
+      String realSchemaName = resolve(schemaName);
 
-        db.connect();
+      if (db.checkTableExists(realSchemaName, realTableName)) {
+        if (isDetailed()) {
+          logDetailed(
+              BaseMessages.getString(PKG, 
"ActionColumnsExist.Log.TableExists", realTableName));
+        }
 
-        if (db.checkTableExists(realSchemaName, realTableName)) {
-          if (isDetailed()) {
-            logDetailed(
-                BaseMessages.getString(PKG, 
"ActionColumnsExist.Log.TableExists", realTableName));
+        for (ColumnExist column : columns) {
+          if (parentWorkflow != null && parentWorkflow.isStopped()) {
+            break;
           }
 
-          for (ColumnExist column : columns) {
-            if (parentWorkflow.isStopped()) {
-              break;
-            }
+          String realColumnname = resolve(column.getName());
 
-            String realColumnname = resolve(column.getName());
-
-            if (db.checkColumnExists(realSchemaName, realTableName, 
realColumnname)) {
-              if (isDetailed()) {
-                logDetailed(
-                    BaseMessages.getString(
-                        PKG, "ActionColumnsExist.Log.ColumnExists", 
realColumnname, realTableName));
-              }
-              nrexistcolums++;
-            } else {
-              logError(
+          if (db.checkColumnExists(realSchemaName, realTableName, 
realColumnname)) {
+            if (isDetailed()) {
+              logDetailed(
                   BaseMessages.getString(
-                      PKG,
-                      "ActionColumnsExist.Log.ColumnNotExists",
-                      realColumnname,
-                      realTableName));
-              nrnotexistcolums++;
+                      PKG, "ActionColumnsExist.Log.ColumnExists", 
realColumnname, realTableName));
             }
+            nrexistcolums++;
+          } else {
+            logError(
+                BaseMessages.getString(
+                    PKG, "ActionColumnsExist.Log.ColumnNotExists", 
realColumnname, realTableName));
+            nrnotexistcolums++;
           }
-        } else {
-          logError(
-              BaseMessages.getString(PKG, 
"ActionColumnsExist.Log.TableNotExists", realTableName));
         }
-      } catch (HopDatabaseException dbe) {
+      } else {
         logError(
-            BaseMessages.getString(
-                PKG, "ActionColumnsExist.Error.UnexpectedError", 
dbe.getMessage()));
+            BaseMessages.getString(PKG, 
"ActionColumnsExist.Log.TableNotExists", realTableName));
       }
-    } else {
-      logError(BaseMessages.getString(PKG, 
"ActionColumnsExist.Error.NoDbConnection"));
+    } catch (HopDatabaseException dbe) {
+      logError(
+          BaseMessages.getString(
+              PKG, "ActionColumnsExist.Error.UnexpectedError", 
dbe.getMessage()));
     }
 
     result.setEntryNr(nrnotexistcolums);
     result.setNrLinesWritten(nrexistcolums);
-    // result is true only if all columns found
-    if (nrexistcolums == columns.size()) {
+    // result is true only if all columns found and columns list is not empty
+    if (!columns.isEmpty() && nrexistcolums == columns.size()) {
       result.setNrErrors(0);
       result.setResult(true);
     }
     return result;
   }
 
+  Database getDatabase(DatabaseMeta databaseMeta) {
+    return new Database(this, this, databaseMeta);
+  }
+
   @Override
   public List<ResourceReference> getResourceDependencies(
       IVariables variables, WorkflowMeta workflowMeta) {
     List<ResourceReference> references = 
super.getResourceDependencies(variables, workflowMeta);
 
-    DatabaseMeta databaseMeta = 
parentWorkflowMeta.findDatabase(connectionName, getVariables());
+    DatabaseMeta databaseMeta = null;
+    if (parentWorkflowMeta != null) {
+      databaseMeta = parentWorkflowMeta.findDatabase(connectionName, 
getVariables());
+    }
     if (databaseMeta != null) {
       ResourceReference reference = new ResourceReference(this);
       reference
diff --git 
a/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistDialog.java
 
b/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistDialog.java
index 2e6e5f69b4..8f4ba9d78f 100644
--- 
a/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistDialog.java
+++ 
b/plugins/actions/columnsexist/src/main/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistDialog.java
@@ -18,7 +18,9 @@
 package org.apache.hop.workflow.actions.columnsexist;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.database.Database;
@@ -229,24 +231,31 @@ public class ActionColumnsExistDialog extends 
ActionDialog {
 
   private void getTableName() {
     String databaseName = wConnection.getText();
-    if (StringUtils.isNotEmpty(databaseName)) {
-      DatabaseMeta databaseMeta = wConnection.loadSelectedElement();
-      if (databaseMeta != null) {
-        DatabaseExplorerDialog std =
-            new DatabaseExplorerDialog(
-                shell, SWT.NONE, variables, databaseMeta, 
this.getWorkflowMeta().getDatabases());
-        std.setSelectedSchemaAndTable(wSchemaname.getText(), 
wTablename.getText());
-        if (std.open()) {
-          wSchemaname.setText(Const.NVL(std.getSchemaName(), ""));
-          wTablename.setText(Const.NVL(std.getTableName(), ""));
-        }
-      } else {
-        MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
-        mb.setMessage(
-            BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
-        mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
-        mb.open();
+    if (StringUtils.isEmpty(databaseName)) {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(
+          BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
+      return;
+    }
+
+    DatabaseMeta databaseMeta = wConnection.loadSelectedElement();
+    if (databaseMeta != null) {
+      DatabaseExplorerDialog std =
+          new DatabaseExplorerDialog(
+              shell, SWT.NONE, variables, databaseMeta, 
this.getWorkflowMeta().getDatabases());
+      std.setSelectedSchemaAndTable(wSchemaname.getText(), 
wTablename.getText());
+      if (std.open()) {
+        wSchemaname.setText(Const.NVL(std.getSchemaName(), ""));
+        wTablename.setText(Const.NVL(std.getTableName(), ""));
       }
+    } else {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(
+          BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
     }
   }
 
@@ -319,40 +328,59 @@ public class ActionColumnsExistDialog extends 
ActionDialog {
 
   /** Get a list of columns */
   private void getListColumns() {
-    if (!Utils.isEmpty(wTablename.getText())) {
-      DatabaseMeta databaseMeta = wConnection.loadSelectedElement();
-      if (databaseMeta != null) {
-        try (Database database = new Database(loggingObject, variables, 
databaseMeta)) {
-          database.connect();
-          IRowMeta row =
-              database.getTableFieldsMeta(
-                  variables.resolve(wSchemaname.getText()),
-                  variables.resolve(wTablename.getText()));
-          if (row != null) {
-            String[] available = row.getFieldNames();
-
-            wFields.removeAll();
-            for (String s : available) {
-              wFields.add(s);
-            }
-            wFields.removeEmptyRows();
-            wFields.setRowNums();
-          } else {
-            MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
-            mb.setMessage(
-                BaseMessages.getString(PKG, 
"ActionColumnsExist.GetListColumsNoRow.DialogMessage"));
-            mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
-            mb.open();
+    if (Utils.isEmpty(wConnection.getText())) {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(
+          BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
+      return;
+    }
+    if (Utils.isEmpty(wTablename.getText())) {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(BaseMessages.getString(PKG, 
"ActionColumnsExist.Error.TablenameEmpty"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
+      return;
+    }
+
+    DatabaseMeta databaseMeta = wConnection.loadSelectedElement();
+    if (databaseMeta != null) {
+      try (Database database = new Database(loggingObject, variables, 
databaseMeta)) {
+        database.connect();
+        IRowMeta row =
+            database.getTableFieldsMeta(
+                variables.resolve(wSchemaname.getText()), 
variables.resolve(wTablename.getText()));
+        if (row != null) {
+          String[] available = row.getFieldNames();
+
+          wFields.removeAll();
+          for (String s : available) {
+            wFields.add(s);
           }
-        } catch (Exception e) {
-          new ErrorDialog(
-              shell,
-              BaseMessages.getString(PKG, CONST_ERROR_TITLE),
-              BaseMessages.getString(
-                  PKG, "ActionColumnsExist.ConnectionError2.DialogMessage", 
wTablename.getText()),
-              e);
+          wFields.removeEmptyRows();
+          wFields.setRowNums();
+        } else {
+          MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+          mb.setMessage(
+              BaseMessages.getString(PKG, 
"ActionColumnsExist.GetListColumsNoRow.DialogMessage"));
+          mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+          mb.open();
         }
+      } catch (Exception e) {
+        new ErrorDialog(
+            shell,
+            BaseMessages.getString(PKG, CONST_ERROR_TITLE),
+            BaseMessages.getString(
+                PKG, "ActionColumnsExist.ConnectionError2.DialogMessage", 
wTablename.getText()),
+            e);
       }
+    } else {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(
+          BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
     }
   }
 
@@ -360,14 +388,26 @@ public class ActionColumnsExistDialog extends 
ActionDialog {
     if (wSchemaname.isDisposed()) {
       return;
     }
+    if (Utils.isEmpty(wConnection.getText())) {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(
+          BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
+      return;
+    }
     DatabaseMeta databaseMeta = wConnection.loadSelectedElement();
     if (databaseMeta != null) {
       try (Database database = new Database(loggingObject, variables, 
databaseMeta)) {
         database.connect();
         String[] schemas = database.getSchemas();
 
+        if (schemas != null) {
+          schemas = 
Arrays.stream(schemas).filter(Objects::nonNull).toArray(String[]::new);
+        }
+
         if (null != schemas && schemas.length > 0) {
-          schemas = Const.sortStrings(schemas);
+          Const.sortStrings(schemas);
           EnterSelectionDialog dialog =
               new EnterSelectionDialog(
                   shell,
@@ -394,6 +434,12 @@ public class ActionColumnsExistDialog extends ActionDialog 
{
             BaseMessages.getString(PKG, 
"System.Dialog.AvailableSchemas.ConnectionError"),
             e);
       }
+    } else {
+      MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+      mb.setMessage(
+          BaseMessages.getString(PKG, 
"ActionColumnsExist.ConnectionError.DialogMessage"));
+      mb.setText(BaseMessages.getString(PKG, CONST_ERROR_TITLE));
+      mb.open();
     }
   }
 }
diff --git 
a/plugins/actions/columnsexist/src/test/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistTest.java
 
b/plugins/actions/columnsexist/src/test/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistTest.java
index edd7ea168d..46b854598b 100644
--- 
a/plugins/actions/columnsexist/src/test/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistTest.java
+++ 
b/plugins/actions/columnsexist/src/test/java/org/apache/hop/workflow/actions/columnsexist/ActionColumnsExistTest.java
@@ -17,19 +17,44 @@
 
 package org.apache.hop.workflow.actions.columnsexist;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
 import org.apache.hop.core.HopClientEnvironment;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.database.Database;
 import org.apache.hop.core.database.DatabaseMeta;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.core.variables.Variables;
 import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.apache.hop.workflow.WorkflowMeta;
 import org.apache.hop.workflow.action.ActionSerializationTestUtil;
+import 
org.apache.hop.workflow.actions.columnsexist.ActionColumnsExist.ColumnExist;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 /** Unit tests for column exist action. */
 class ActionColumnsExistTest {
 
+  @BeforeAll
+  static void setUp() throws Exception {
+    HopClientEnvironment.init();
+  }
+
   @Test
   void testSerialization() throws Exception {
-    HopClientEnvironment.init();
     DatabaseMeta databaseMeta = new DatabaseMeta();
     databaseMeta.setName("unit-test-db");
     databaseMeta.setDatabaseType("NONE");
@@ -47,4 +72,179 @@ class ActionColumnsExistTest {
     Assertions.assertEquals("F1", action.getColumns().get(0).getName());
     Assertions.assertEquals("F2", action.getColumns().get(1).getName());
   }
+
+  @Test
+  void testExecuteWithNoConnection() {
+    ActionColumnsExist action = new ActionColumnsExist();
+    action.setConnectionName(null);
+    action.setTableName("test-table");
+    List<ColumnExist> columns = new ArrayList<>();
+    columns.add(new ColumnExist("c1"));
+    action.setColumns(columns);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.getResult());
+    assertEquals(1, result.getNrErrors());
+  }
+
+  @Test
+  void testExecuteWithNonExistentConnection() {
+    ActionColumnsExist action = new ActionColumnsExist();
+    action.setConnectionName("non-existent-db");
+    action.setTableName("test-table");
+    List<ColumnExist> columns = new ArrayList<>();
+    columns.add(new ColumnExist("c1"));
+    action.setColumns(columns);
+
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    when(workflowMeta.findDatabase(anyString(), any())).thenReturn(null);
+
+    action.setParentWorkflowMeta(workflowMeta);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.getResult());
+    assertEquals(1, result.getNrErrors());
+  }
+
+  @Test
+  void testExecuteWithEmptyTableName() {
+    ActionColumnsExist action = new ActionColumnsExist();
+    action.setConnectionName("unit-test-db");
+    action.setTableName(null);
+
+    DatabaseMeta databaseMeta = mock(DatabaseMeta.class);
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    when(workflowMeta.findDatabase(anyString(), 
any())).thenReturn(databaseMeta);
+
+    action.setParentWorkflowMeta(workflowMeta);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.getResult());
+    assertEquals(1, result.getNrErrors());
+  }
+
+  @Test
+  void testExecuteWithEmptyColumns() {
+    ActionColumnsExist action = new ActionColumnsExist();
+    action.setConnectionName("unit-test-db");
+    action.setTableName("test-table");
+    action.setColumns(new ArrayList<>());
+
+    DatabaseMeta databaseMeta = mock(DatabaseMeta.class);
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    when(workflowMeta.findDatabase(anyString(), 
any())).thenReturn(databaseMeta);
+
+    action.setParentWorkflowMeta(workflowMeta);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.getResult());
+    assertEquals(1, result.getNrErrors());
+  }
+
+  @Test
+  void testExecuteSuccess() throws Exception {
+    ActionColumnsExist action = spy(new ActionColumnsExist());
+    action.setConnectionName("unit-test-db");
+    action.setTableName("test-table");
+    List<ColumnExist> columns = new ArrayList<>();
+    columns.add(new ColumnExist("c1"));
+    columns.add(new ColumnExist("c2"));
+    action.setColumns(columns);
+
+    DatabaseMeta databaseMeta = mock(DatabaseMeta.class);
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    when(workflowMeta.findDatabase(anyString(), 
any())).thenReturn(databaseMeta);
+    action.setParentWorkflowMeta(workflowMeta);
+
+    Database db = mock(Database.class);
+    when(db.checkTableExists(any(), eq("test-table"))).thenReturn(true);
+    when(db.checkColumnExists(any(), eq("test-table"), 
eq("c1"))).thenReturn(true);
+    when(db.checkColumnExists(any(), eq("test-table"), 
eq("c2"))).thenReturn(true);
+
+    doReturn(db).when(action).getDatabase(databaseMeta);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertTrue(result.getResult());
+    assertEquals(0, result.getNrErrors());
+    assertEquals(2, result.getNrLinesWritten());
+    assertEquals(0, result.getEntryNr());
+  }
+
+  @Test
+  void testExecuteTableNotExists() throws Exception {
+    ActionColumnsExist action = spy(new ActionColumnsExist());
+    action.setConnectionName("unit-test-db");
+    action.setTableName("test-table");
+    List<ColumnExist> columns = new ArrayList<>();
+    columns.add(new ColumnExist("c1"));
+    action.setColumns(columns);
+
+    DatabaseMeta databaseMeta = mock(DatabaseMeta.class);
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    when(workflowMeta.findDatabase(anyString(), 
any())).thenReturn(databaseMeta);
+    action.setParentWorkflowMeta(workflowMeta);
+
+    Database db = mock(Database.class);
+    when(db.checkTableExists(any(), eq("test-table"))).thenReturn(false);
+
+    doReturn(db).when(action).getDatabase(databaseMeta);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.getResult());
+    assertEquals(1, result.getNrErrors());
+  }
+
+  @Test
+  void testExecuteColumnNotExists() throws Exception {
+    ActionColumnsExist action = spy(new ActionColumnsExist());
+    action.setConnectionName("unit-test-db");
+    action.setTableName("test-table");
+    List<ColumnExist> columns = new ArrayList<>();
+    columns.add(new ColumnExist("c1"));
+    columns.add(new ColumnExist("c2"));
+    action.setColumns(columns);
+
+    DatabaseMeta databaseMeta = mock(DatabaseMeta.class);
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    when(workflowMeta.findDatabase(anyString(), 
any())).thenReturn(databaseMeta);
+    action.setParentWorkflowMeta(workflowMeta);
+
+    Database db = mock(Database.class);
+    when(db.checkTableExists(any(), eq("test-table"))).thenReturn(true);
+    when(db.checkColumnExists(any(), eq("test-table"), 
eq("c1"))).thenReturn(true);
+    when(db.checkColumnExists(any(), eq("test-table"), 
eq("c2"))).thenReturn(false);
+
+    doReturn(db).when(action).getDatabase(databaseMeta);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.getResult());
+    assertEquals(1, result.getNrErrors());
+    assertEquals(1, result.getNrLinesWritten());
+    assertEquals(1, result.getEntryNr());
+  }
+
+  @Test
+  void testCheckRemarks() {
+    ActionColumnsExist action = new ActionColumnsExist();
+    action.setTableName(null);
+    action.setColumns(null);
+
+    List<ICheckResult> remarks = new ArrayList<>();
+    WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+    IVariables variables = new Variables();
+
+    action.check(remarks, workflowMeta, variables, null);
+
+    assertFalse(remarks.isEmpty());
+    assertEquals(2, remarks.size());
+    assertEquals(ICheckResult.TYPE_RESULT_ERROR, remarks.get(0).getType());
+    assertEquals(ICheckResult.TYPE_RESULT_WARNING, remarks.get(1).getType());
+  }
 }

Reply via email to