This is an automated email from the ASF dual-hosted git repository.
hansva 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 a998b0008d Clear filter in database perspective when switching
projects, fixes #8453 (#8485)
a998b0008d is described below
commit a998b0008d0e599d7ce19297b0913cde9f509804
Author: Matt Casters <[email protected]>
AuthorDate: Mon Sep 21 13:15:16 2026 +0200
Clear filter in database perspective when switching projects, fixes #8453
(#8485)
---
.../perspective/database/DatabaseWorkbench.java | 154 +++++++++++----------
.../database/DatabaseWorkbenchFilterTest.java | 109 +++++++++++++++
2 files changed, 189 insertions(+), 74 deletions(-)
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
index fd2b5f5a05..0133555fac 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
@@ -257,6 +257,7 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
e ->
host.asyncExec(
() -> {
+ clearSearchFilter(false);
closeSqlEditorTabs();
operationsPanel.cancelAll();
operationsPanel.clearAll();
@@ -427,12 +428,19 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
}
public void clearSearchFilter() {
+ clearSearchFilter(true);
+ }
+
+ public void clearSearchFilter(boolean rebuildTree) {
if (searchText != null && !searchText.isDisposed()) {
searchText.setText("");
}
+ cancelScheduledFilterApply();
filterText = "";
filterMatcher = new SearchMatcher("", false, false, false);
- rebuildTree();
+ if (rebuildTree) {
+ rebuildTree();
+ }
}
private void scheduleFilterApply() {
@@ -463,9 +471,6 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
try {
tree.removeAll();
for (DatabaseConnectionState state : connections.values()) {
- if (!connectionMatches(state)) {
- continue;
- }
TreeItem connectionItem = new TreeItem(tree, SWT.NONE);
connectionItem.setText(state.getDatabaseMeta().getName());
connectionItem.setImage(
@@ -542,62 +547,6 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
}
}
- private boolean connectionMatches(DatabaseConnectionState state) {
- if (Utils.isEmpty(filterText)) {
- return true;
- }
- DatabaseMeta meta = state.getDatabaseMeta();
- if (filterMatcher.matches(meta.getName())) {
- return true;
- }
- DatabaseMetaInformation info = state.getInformation();
- if (info == null) {
- return false;
- }
- if (info.getSchemas() != null) {
- for (Schema schema : info.getSchemas()) {
- if (filterMatcher.matches(schema.getSchemaName())) {
- return true;
- }
- if (schema.getItems() != null) {
- for (String table : schema.getItems()) {
- if (filterMatcher.matches(table)) {
- return true;
- }
- }
- }
- }
- }
- if (info.getTables() != null) {
- for (String table : info.getTables()) {
- if (filterMatcher.matches(table)) {
- return true;
- }
- }
- }
- if (mapHasMatch(info.getViewMap()) || mapHasMatch(info.getSynonymMap())) {
- return true;
- }
- return false;
- }
-
- private boolean mapHasMatch(Map<String, Collection<String>> map) {
- if (map == null) {
- return false;
- }
- for (Collection<String> names : map.values()) {
- if (names == null) {
- continue;
- }
- for (String name : names) {
- if (filterMatcher.matches(name)) {
- return true;
- }
- }
- }
- return false;
- }
-
private void fillConnectionChildren(TreeItem connectionItem,
DatabaseConnectionState state) {
DatabaseMetaInformation info = state.getInformation();
String connectionName = state.getDatabaseMeta().getName();
@@ -619,6 +568,9 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
Catalog[] catalogs = info.getCatalogs();
if (catalogs != null && catalogs.length > 0) {
for (Catalog catalog : catalogs) {
+ if (!catalogOrChildMatches(catalog, info)) {
+ continue;
+ }
TreeItem catalogItem = new TreeItem(connectionItem, SWT.NONE);
catalogItem.setText(Const.NVL(catalog.getCatalogName(), ""));
catalogItem.setImage(GuiResource.getInstance().getImageFolder());
@@ -649,22 +601,72 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
}
private boolean schemaOrChildMatches(Schema schema, DatabaseMetaInformation
info) {
+ return schemaOrChildMatches(filterMatcher, filterText, schema, info);
+ }
+
+ static boolean schemaOrChildMatches(
+ SearchMatcher matcher, String filterText, Schema schema,
DatabaseMetaInformation info) {
if (Utils.isEmpty(filterText)) {
return true;
}
- if (filterMatcher.matches(schema.getSchemaName())) {
+ if (matcher.matches(schema.getSchemaName())) {
return true;
}
if (schema.getItems() != null) {
for (String table : schema.getItems()) {
- if (filterMatcher.matches(table)) {
+ if (matcher.matches(table)) {
return true;
}
}
}
- for (String view : DatabaseTreeUtil.namesForSchema(info.getViewMap(),
schema.getSchemaName())) {
- if (filterMatcher.matches(view)) {
- return true;
+ if (info != null) {
+ for (String view :
+ DatabaseTreeUtil.namesForSchema(info.getViewMap(),
schema.getSchemaName())) {
+ if (matcher.matches(view)) {
+ return true;
+ }
+ }
+ for (String synonym :
+ DatabaseTreeUtil.namesForSchema(info.getSynonymMap(),
schema.getSchemaName())) {
+ if (matcher.matches(synonym)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean catalogOrChildMatches(Catalog catalog,
DatabaseMetaInformation info) {
+ return catalogOrChildMatches(filterMatcher, filterText, catalog, info);
+ }
+
+ static boolean catalogOrChildMatches(
+ SearchMatcher matcher, String filterText, Catalog catalog,
DatabaseMetaInformation info) {
+ if (Utils.isEmpty(filterText)) {
+ return true;
+ }
+ if (matcher.matches(catalog.getCatalogName())) {
+ return true;
+ }
+ if (catalog.getItems() != null) {
+ for (String table : catalog.getItems()) {
+ if (matcher.matches(table)) {
+ return true;
+ }
+ }
+ }
+ if (info != null) {
+ for (String view :
+ DatabaseTreeUtil.namesForSchema(info.getViewMap(),
catalog.getCatalogName())) {
+ if (matcher.matches(view)) {
+ return true;
+ }
+ }
+ for (String synonym :
+ DatabaseTreeUtil.namesForSchema(info.getSynonymMap(),
catalog.getCatalogName())) {
+ if (matcher.matches(synonym)) {
+ return true;
+ }
}
}
return false;
@@ -698,7 +700,7 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
}
names.sort(String.CASE_INSENSITIVE_ORDER);
for (String name : names) {
- if (!matchesFilter(name, schemaName, connectionName)) {
+ if (!matchesFilter(name, schemaName)) {
continue;
}
DatabaseTreeNode.Kind kind = DatabaseTreeUtil.kindOf(name, views,
synonyms);
@@ -709,13 +711,16 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
}
}
- private boolean matchesFilter(String name, String schemaName, String
connectionName) {
+ private boolean matchesFilter(String name, String schemaName) {
+ return matchesFilter(filterMatcher, filterText, name, schemaName);
+ }
+
+ static boolean matchesFilter(
+ SearchMatcher matcher, String filterText, String name, String
schemaName) {
if (Utils.isEmpty(filterText)) {
return true;
}
- return filterMatcher.matches(name)
- || filterMatcher.matches(schemaName)
- || filterMatcher.matches(connectionName);
+ return matcher.matches(name) || (schemaName != null &&
matcher.matches(schemaName));
}
private void addFolder(
@@ -732,6 +737,10 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
folder.setImage(GuiResource.getInstance().getImageFolder());
folder.setData(DatabaseTreeNode.folder(connectionName, folderName));
addTables(folder, connectionName, null, names, kind);
+ if (!Utils.isEmpty(filterText) && folder.getItemCount() == 0) {
+ folder.dispose();
+ return;
+ }
FolderTreeIcons.setExpanded(folder, true);
}
@@ -745,10 +754,7 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
return;
}
for (String name : names) {
- if (!Utils.isEmpty(filterText)
- && !filterMatcher.matches(name)
- && !filterMatcher.matches(schemaName)
- && !filterMatcher.matches(connectionName)) {
+ if (!matchesFilter(name, schemaName)) {
continue;
}
TreeItem item = new TreeItem(parent, SWT.NONE);
diff --git
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchFilterTest.java
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchFilterTest.java
new file mode 100644
index 0000000000..bfdbc1e6ae
--- /dev/null
+++
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchFilterTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.ui.hopgui.perspective.database;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import org.apache.hop.core.database.Catalog;
+import org.apache.hop.core.database.DatabaseMetaInformation;
+import org.apache.hop.core.database.Schema;
+import org.apache.hop.core.search.SearchMatcher;
+import org.junit.jupiter.api.Test;
+
+class DatabaseWorkbenchFilterTest {
+
+ @Test
+ void matchesFilterReturnsTrueWhenFilterIsEmpty() {
+ SearchMatcher matcher = new SearchMatcher("", false, false, false);
+ assertTrue(DatabaseWorkbench.matchesFilter(matcher, "", "customers",
"public"));
+ assertTrue(DatabaseWorkbench.matchesFilter(matcher, null, "customers",
"public"));
+ }
+
+ @Test
+ void matchesFilterMatchesTableName() {
+ SearchMatcher matcher = new SearchMatcher("cust", false, false, false);
+ assertTrue(DatabaseWorkbench.matchesFilter(matcher, "cust", "customers",
"public"));
+ assertTrue(DatabaseWorkbench.matchesFilter(matcher, "cust",
"CUSTOMER_ORDER", "public"));
+ assertFalse(DatabaseWorkbench.matchesFilter(matcher, "cust", "orders",
"public"));
+ }
+
+ @Test
+ void matchesFilterMatchesSchemaName() {
+ SearchMatcher matcher = new SearchMatcher("pub", false, false, false);
+ assertTrue(DatabaseWorkbench.matchesFilter(matcher, "pub", "orders",
"public"));
+ assertFalse(DatabaseWorkbench.matchesFilter(matcher, "pub", "orders",
"analytics"));
+ }
+
+ @Test
+ void schemaOrChildMatchesWithEmptyFilter() {
+ SearchMatcher matcher = new SearchMatcher("", false, false, false);
+ Schema schema = new Schema("public", new String[] {"customers"});
+ assertTrue(DatabaseWorkbench.schemaOrChildMatches(matcher, "", schema,
null));
+ }
+
+ @Test
+ void schemaOrChildMatchesSchemaName() {
+ SearchMatcher matcher = new SearchMatcher("pub", false, false, false);
+ Schema schema = new Schema("public", new String[] {"orders"});
+ assertTrue(DatabaseWorkbench.schemaOrChildMatches(matcher, "pub", schema,
null));
+ }
+
+ @Test
+ void schemaOrChildMatchesTableName() {
+ SearchMatcher matcher = new SearchMatcher("cust", false, false, false);
+ Schema schema = new Schema("sales", new String[] {"customers", "orders"});
+ assertTrue(DatabaseWorkbench.schemaOrChildMatches(matcher, "cust", schema,
null));
+
+ Schema other = new Schema("sales", new String[] {"orders", "products"});
+ assertFalse(DatabaseWorkbench.schemaOrChildMatches(matcher, "cust", other,
null));
+ }
+
+ @Test
+ void schemaOrChildMatchesViewsAndSynonyms() {
+ SearchMatcher matcher = new SearchMatcher("view_order", false, false,
false);
+ Schema schema = new Schema("sales", new String[] {"customers"});
+
+ DatabaseMetaInformation info = mock(DatabaseMetaInformation.class);
+ Map<String, Collection<String>> viewMap = Map.of("sales",
List.of("view_orders"));
+ when(info.getViewMap()).thenReturn(viewMap);
+
+ assertTrue(DatabaseWorkbench.schemaOrChildMatches(matcher, "view_order",
schema, info));
+ }
+
+ @Test
+ void catalogOrChildMatchesCatalogNameOrItems() {
+ SearchMatcher emptyMatcher = new SearchMatcher("", false, false, false);
+ Catalog catalog = new Catalog("cat1", new String[] {"orders"});
+ assertTrue(DatabaseWorkbench.catalogOrChildMatches(emptyMatcher, "",
catalog, null));
+
+ SearchMatcher nameMatcher = new SearchMatcher("cat1", false, false, false);
+ assertTrue(DatabaseWorkbench.catalogOrChildMatches(nameMatcher, "cat1",
catalog, null));
+
+ SearchMatcher itemMatcher = new SearchMatcher("ord", false, false, false);
+ assertTrue(DatabaseWorkbench.catalogOrChildMatches(itemMatcher, "ord",
catalog, null));
+
+ SearchMatcher noMatcher = new SearchMatcher("cust", false, false, false);
+ assertFalse(DatabaseWorkbench.catalogOrChildMatches(noMatcher, "cust",
catalog, null));
+ }
+}