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 34679ea5c3d..605b0a0da19 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 @@ 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.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 @@ this, this, getParentWorkflowMeta().findDatabase(connection, getVariables()))) { } } } 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 boolean isArgFromPrevious() { public void setArgFromPrevious(boolean argFromPrevious) { this.argFromPrevious = argFromPrevious; } + + @Override + public void check( + List 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 16823d259e6..82a2b89469b 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 @@ private void ok() { } 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> tableMap = database.getTableMap(); + List displayList = new ArrayList<>(); + List schemaTableList = new ArrayList<>(); + + if (tableMap != null && !tableMap.isEmpty()) { + List schemas = new ArrayList<>(tableMap.keySet()); + Collections.sort(schemas, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)); + for (String schema : schemas) { + Collection tableCollection = tableMap.get(schema); + if (tableCollection != null) { + List 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 23890952aaa..da956258325 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 00000000000..e3c1238b900 --- /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 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 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()); + } +}