diff --git a/server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls b/server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls index 81c1add2c5..790196f905 100644 --- a/server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls +++ b/server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls @@ -148,14 +148,15 @@ type SQLExecutionPlan { } type SQLExecutionPlanNode { + id: ID! + parentId: ID + kind: String! name: String type: String! condition: String description: String properties: [ObjectPropertyInfo!]! - - nested: [SQLExecutionPlanNode!]! } #################################################### diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlan.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlan.java index 8daaf617ff..20f63dec4f 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlan.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlan.java @@ -19,9 +19,9 @@ package io.cloudbeaver.service.sql; import io.cloudbeaver.model.session.WebSession; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.exec.plan.DBCPlan; +import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; /** * WebSQLExecutionPlan. @@ -44,10 +44,28 @@ public class WebSQLExecutionPlan { public WebSQLExecutionPlanNode[] getNodes() { Map options = new LinkedHashMap<>(); - return plan.getPlanNodes(options) - .stream() - .map(node -> new WebSQLExecutionPlanNode(webSession, node)) - .toArray(WebSQLExecutionPlanNode[]::new); + Map idMap = new IdentityHashMap<>(); + + List result = new ArrayList<>(); + + for (DBCPlanNode node : plan.getPlanNodes(options)) { + addNodeWithNested(result, null, node, idMap); + } + + return result.toArray(new WebSQLExecutionPlanNode[0]); + } + + private void addNodeWithNested(List result, DBCPlanNode parentNode, DBCPlanNode node, Map idMap) { + String parentId = idMap.get(parentNode); + String nodeId = String.valueOf(idMap.size()); + idMap.put(node, nodeId); + result.add(new WebSQLExecutionPlanNode(webSession, node, nodeId, parentId)); + Collection nested = node.getNested(); + if (nested != null) { + for (DBCPlanNode nn : nested) { + addNodeWithNested(result, node, nn, idMap); + } + } } } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlanNode.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlanNode.java index ef05591992..d16d1040c7 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlanNode.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLExecutionPlanNode.java @@ -23,10 +23,8 @@ import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode; import org.jkiss.dbeaver.runtime.properties.ObjectPropertyDescriptor; import org.jkiss.dbeaver.runtime.properties.PropertyCollector; -import org.jkiss.utils.CommonUtils; import java.util.Arrays; -import java.util.Collection; /** * WebSQLExecutionPlanNode. @@ -37,10 +35,22 @@ public class WebSQLExecutionPlanNode { private final WebSession webSession; private final DBCPlanNode node; + private final String id; + private final String parentId; - public WebSQLExecutionPlanNode(WebSession webSession, DBCPlanNode node) { + public WebSQLExecutionPlanNode(WebSession webSession, DBCPlanNode node, String id, String parentId) { this.webSession = webSession; this.node = node; + this.id = id; + this.parentId = parentId; + } + + public String getId() { + return id; + } + + public String getParentId() { + return parentId; } public String getKind() { @@ -72,15 +82,4 @@ public class WebSQLExecutionPlanNode { .map(p -> new WebPropertyInfo(webSession, p, propertyCollector)).toArray(WebPropertyInfo[]::new); } - public WebSQLExecutionPlanNode[] getNested() { - Collection nestedNodes = node.getNested(); - if (CommonUtils.isEmpty(nestedNodes)) { - return null; - } - return nestedNodes - .stream() - .map(node1 -> new WebSQLExecutionPlanNode(webSession, node1)) - .toArray(WebSQLExecutionPlanNode[]::new); - } - }