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 8eb9a1e790 Issue #8777: Fix false positive result on error and
populate schema in Action Truncate tables (#8778)
8eb9a1e790 is described below
commit 8eb9a1e79059e7c1cc45b1d0e437765fe8a9e2a7
Author: Samuel Willyanto <[email protected]>
AuthorDate: Sat Oct 10 00:42:41 2026 +0700
Issue #8777: Fix false positive result on error and populate schema in
Action Truncate tables (#8778)
---
.../truncatetables/ActionTruncateTables.java | 40 +++++++-
.../truncatetables/ActionTruncateTablesDialog.java | 111 +++++++++++++++------
.../messages/messages_en_US.properties | 2 +
.../truncatetables/ActionTruncateTablesTest.java | 107 ++++++++++++++++++++
4 files changed, 227 insertions(+), 33 deletions(-)
diff --git
a/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTables.java
b/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTables.java
index 34679ea5c3..605b0a0da1 100644
---
a/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTables.java
+++
b/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTables.java
@@ -19,6 +19,9 @@ package org.apache.hop.workflow.actions.truncatetables;
import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hop.core.CheckResult;
+import org.apache.hop.core.ICheckResult;
import org.apache.hop.core.Result;
import org.apache.hop.core.RowMetaAndData;
import org.apache.hop.core.annotations.Action;
@@ -28,6 +31,7 @@ import org.apache.hop.core.variables.IVariables;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.metadata.api.HopMetadataProperty;
import org.apache.hop.metadata.api.HopMetadataPropertyType;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.resource.ResourceEntry;
import org.apache.hop.resource.ResourceEntry.ResourceType;
import org.apache.hop.resource.ResourceReference;
@@ -216,13 +220,13 @@ public class ActionTruncateTables extends ActionBase
implements Cloneable, IActi
}
}
} catch (Exception dbe) {
- result.setNrErrors(1);
+ updateErrors();
logError(
BaseMessages.getString(
PKG, "ActionTruncateTables.Error.RunningEntry",
dbe.getMessage()));
}
} else {
- result.setNrErrors(1);
+ updateErrors();
logError(BaseMessages.getString(PKG,
"ActionTruncateTables.NoDbConnection"));
}
@@ -266,4 +270,36 @@ public class ActionTruncateTables extends ActionBase
implements Cloneable, IActi
public void setArgFromPrevious(boolean argFromPrevious) {
this.argFromPrevious = argFromPrevious;
}
+
+ @Override
+ public void check(
+ List<ICheckResult> remarks,
+ WorkflowMeta workflowMeta,
+ IVariables variables,
+ IHopMetadataProvider metadataProvider) {
+
+ String realConnection = variables.resolve(connection);
+ if (Utils.isEmpty(realConnection)
+ || workflowMeta == null
+ || workflowMeta.findDatabase(realConnection, variables) == null) {
+ String message = BaseMessages.getString(PKG,
"ActionTruncateTables.NoDbConnection");
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_WARNING, message,
this));
+ }
+
+ if (!argFromPrevious) {
+ if (Utils.isEmpty(items)) {
+ String message =
+ BaseMessages.getString(PKG,
"ActionTruncateTables.CheckResult.NoTablesSelected");
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_WARNING, message,
this));
+ } else {
+ for (TruncateTableItem item : items) {
+ if (StringUtils.isEmpty(variables.resolve(item.getTableName()))) {
+ String message =
+ BaseMessages.getString(PKG,
"ActionTruncateTables.CheckResult.TableNameIsEmpty");
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_WARNING,
message, this));
+ }
+ }
+ }
+ }
+ }
}
diff --git
a/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesDialog.java
b/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesDialog.java
index 16823d259e..82a2b89469 100644
---
a/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesDialog.java
+++
b/plugins/actions/truncatetables/src/main/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesDialog.java
@@ -17,11 +17,15 @@
package org.apache.hop.workflow.actions.truncatetables;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
+import org.apache.hop.core.Const;
import org.apache.hop.core.database.Database;
import org.apache.hop.core.database.DatabaseMeta;
-import org.apache.hop.core.exception.HopDatabaseException;
import org.apache.hop.core.util.Utils;
import org.apache.hop.core.variables.IVariables;
import org.apache.hop.i18n.BaseMessages;
@@ -302,38 +306,83 @@ public class ActionTruncateTablesDialog extends
ActionDialog {
}
private void getTableName() {
- DatabaseMeta databaseMeta =
getWorkflowMeta().findDatabase(wConnection.getText(), variables);
- if (databaseMeta != null) {
-
- try (Database database = new Database(loggingObject, variables,
databaseMeta)) {
- database.connect();
- String[] tableNames = database.getTablenames();
- Arrays.sort(tableNames);
- EnterSelectionDialog dialog =
- new EnterSelectionDialog(
- shell,
- tableNames,
- BaseMessages.getString(PKG,
"ActionTruncateTables.SelectTables.Title"),
- BaseMessages.getString(PKG,
"ActionTruncateTables.SelectTables.Message"));
- dialog.setMulti(true);
- dialog.setAvoidQuickSearch();
- if (dialog.open() != null) {
- int[] idx = dialog.getSelectionIndeces();
- for (int j : idx) {
- TableItem tableItem = new TableItem(wFields.table, SWT.NONE);
- tableItem.setText(1, tableNames[j]);
+ String connectionName = wConnection.getText();
+ if (Utils.isEmpty(connectionName)) {
+ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+ mb.setText(BaseMessages.getString(PKG, "System.Dialog.Error.Title"));
+ mb.setMessage(BaseMessages.getString(PKG,
"ActionTruncateTables.NoDbConnection"));
+ mb.open();
+ return;
+ }
+
+ DatabaseMeta databaseMeta = getWorkflowMeta().findDatabase(connectionName,
variables);
+ if (databaseMeta == null) {
+ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+ mb.setText(BaseMessages.getString(PKG, "System.Dialog.Error.Title"));
+ mb.setMessage(BaseMessages.getString(PKG,
"ActionTruncateTables.NoDbConnection"));
+ mb.open();
+ return;
+ }
+
+ try (Database database = new Database(loggingObject, variables,
databaseMeta)) {
+ database.connect();
+ Map<String, Collection<String>> tableMap = database.getTableMap();
+ List<String> displayList = new ArrayList<>();
+ List<String[]> schemaTableList = new ArrayList<>();
+
+ if (tableMap != null && !tableMap.isEmpty()) {
+ List<String> schemas = new ArrayList<>(tableMap.keySet());
+ Collections.sort(schemas,
Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER));
+ for (String schema : schemas) {
+ Collection<String> tableCollection = tableMap.get(schema);
+ if (tableCollection != null) {
+ List<String> tables = new ArrayList<>(tableCollection);
+ Collections.sort(tables,
Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER));
+ for (String table : tables) {
+ String displayName = Utils.isEmpty(schema) ? table : schema +
"." + table;
+ displayList.add(displayName);
+ schemaTableList.add(new String[] {table, Const.NVL(schema, "")});
+ }
}
}
- } catch (HopDatabaseException e) {
- new ErrorDialog(
- shell,
- BaseMessages.getString(PKG, "System.Dialog.Error.Title"),
- BaseMessages.getString(PKG,
"ActionTruncateTables.ConnectionError.DialogMessage"),
- e);
}
- wFields.removeEmptyRows();
- wFields.setRowNums();
- wFields.optWidth(true);
+
+ if (displayList.isEmpty()) {
+ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_WARNING);
+ mb.setText(BaseMessages.getString(PKG, "System.Dialog.Warning.Title"));
+ mb.setMessage(
+ BaseMessages.getString(PKG,
"ActionTruncateTables.ConnectionError.DialogMessage"));
+ mb.open();
+ return;
+ }
+
+ String[] displayArray = displayList.toArray(new String[0]);
+ EnterSelectionDialog dialog =
+ new EnterSelectionDialog(
+ shell,
+ displayArray,
+ BaseMessages.getString(PKG,
"ActionTruncateTables.SelectTables.Title"),
+ BaseMessages.getString(PKG,
"ActionTruncateTables.SelectTables.Message"));
+ dialog.setMulti(true);
+ dialog.setAvoidQuickSearch();
+ if (dialog.open() != null) {
+ int[] idx = dialog.getSelectionIndeces();
+ for (int j : idx) {
+ String[] st = schemaTableList.get(j);
+ TableItem tableItem = new TableItem(wFields.table, SWT.NONE);
+ tableItem.setText(1, st[0]);
+ tableItem.setText(2, st[1]);
+ }
+ }
+ } catch (Exception e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "System.Dialog.Error.Title"),
+ BaseMessages.getString(PKG,
"ActionTruncateTables.ConnectionError.DialogMessage"),
+ e);
}
+ wFields.removeEmptyRows();
+ wFields.setRowNums();
+ wFields.optWidth(true);
}
}
diff --git
a/plugins/actions/truncatetables/src/main/resources/org/apache/hop/workflow/actions/truncatetables/messages/messages_en_US.properties
b/plugins/actions/truncatetables/src/main/resources/org/apache/hop/workflow/actions/truncatetables/messages/messages_en_US.properties
index 23890952aa..da95625832 100644
---
a/plugins/actions/truncatetables/src/main/resources/org/apache/hop/workflow/actions/truncatetables/messages/messages_en_US.properties
+++
b/plugins/actions/truncatetables/src/main/resources/org/apache/hop/workflow/actions/truncatetables/messages/messages_en_US.properties
@@ -18,6 +18,8 @@
#
ActionTruncateTables.ArgEmpty=This argument is empty\!
+ActionTruncateTables.CheckResult.NoTablesSelected=No tables selected to
truncate.
+ActionTruncateTables.CheckResult.TableNameIsEmpty=Table name is empty.
ActionTruncateTables.ConnectionError.DialogMessage=Error\!Can not return table
names list\!
ActionTruncateTables.Description=Truncate one or several tables.
ActionTruncateTables.Error.CanNotFindTable=We can not find table [{0}]\!
diff --git
a/plugins/actions/truncatetables/src/test/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesTest.java
b/plugins/actions/truncatetables/src/test/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesTest.java
new file mode 100644
index 0000000000..e3c1238b90
--- /dev/null
+++
b/plugins/actions/truncatetables/src/test/java/org/apache/hop/workflow/actions/truncatetables/ActionTruncateTablesTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.workflow.actions.truncatetables;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.hop.core.HopClientEnvironment;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.logging.HopLogStore;
+import org.apache.hop.core.logging.LogLevel;
+import org.apache.hop.workflow.Workflow;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+class ActionTruncateTablesTest {
+
+ @BeforeAll
+ static void setUp() throws Exception {
+ HopClientEnvironment.init();
+ HopLogStore.init();
+ }
+
+ @Test
+ void testExecuteWithNoConnection() {
+ ActionTruncateTables action = new ActionTruncateTables();
+ action.setConnection(null);
+
+ Result result = action.execute(new Result(), 0);
+
+ assertFalse(result.getResult());
+ assertEquals(1, result.getNrErrors());
+ }
+
+ @Test
+ void testExecuteWithNonExistentConnection() {
+ ActionTruncateTables action = new ActionTruncateTables();
+ action.setConnection("non-existent-db");
+
+ WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+ when(workflowMeta.findDatabase(anyString(), any())).thenReturn(null);
+
+ Workflow workflow = mock(Workflow.class);
+ when(workflow.getWorkflowMeta()).thenReturn(workflowMeta);
+ when(workflow.getLogLevel()).thenReturn(LogLevel.BASIC);
+
+ action.setParentWorkflow(workflow);
+ action.setParentWorkflowMeta(workflowMeta);
+
+ Result result = action.execute(new Result(), 0);
+
+ assertFalse(result.getResult());
+ assertEquals(1, result.getNrErrors());
+ }
+
+ @Test
+ void testCheckRemarks() {
+ ActionTruncateTables action = new ActionTruncateTables();
+ action.setConnection(null);
+
+ java.util.List<org.apache.hop.core.ICheckResult> remarks = new
java.util.ArrayList<>();
+ WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+ when(workflowMeta.findDatabase(any(), any())).thenReturn(null);
+
+ org.apache.hop.core.variables.Variables variables =
+ new org.apache.hop.core.variables.Variables();
+ action.check(remarks, workflowMeta, variables, null);
+
+ assertFalse(remarks.isEmpty());
+ assertEquals(org.apache.hop.core.ICheckResult.TYPE_RESULT_WARNING,
remarks.get(0).getType());
+ }
+
+ @Test
+ void testCheckRemarksWithArgFromPrevious() {
+ ActionTruncateTables action = new ActionTruncateTables();
+ action.setArgFromPrevious(true);
+ action.setConnection(null);
+
+ java.util.List<org.apache.hop.core.ICheckResult> remarks = new
java.util.ArrayList<>();
+ WorkflowMeta workflowMeta = mock(WorkflowMeta.class);
+
+ action.check(remarks, workflowMeta, new
org.apache.hop.core.variables.Variables(), null);
+
+ assertFalse(remarks.isEmpty());
+ assertEquals(org.apache.hop.core.ICheckResult.TYPE_RESULT_WARNING,
remarks.get(0).getType());
+ }
+}