Skip to content

Dynamically created tabs are shown on explain and profile queries #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.neueda.jetbrains.plugin.graphdb.database.api.query;

import java.util.List;
import java.util.Map;

public interface GraphQueryPlan {

String getOperatorType();

Map<String, Object> getArguments();

List<String> getIdentifiers();

List<? extends GraphQueryPlan> children();

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.neueda.jetbrains.plugin.graphdb.database.api.data.GraphRelationship;

import java.util.List;
import java.util.Optional;

public interface GraphQueryResult {

Expand All @@ -20,4 +21,10 @@ public interface GraphQueryResult {
List<GraphRelationship> getRelationships();

List<GraphQueryNotification> getNotifications();

boolean hasPlan();

boolean isProfilePlan();

Optional<GraphQueryPlan> getPlan();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import com.neueda.jetbrains.plugin.graphdb.database.api.data.GraphNode;
import com.neueda.jetbrains.plugin.graphdb.database.api.data.GraphRelationship;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryNotification;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryPlan;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResultColumn;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResultRow;
import com.neueda.jetbrains.plugin.graphdb.database.neo4j.bolt.data.Neo4jBoltQueryNotification;
import com.neueda.jetbrains.plugin.graphdb.database.neo4j.bolt.data.Neo4jBoltQueryPlan;
import com.neueda.jetbrains.plugin.graphdb.database.neo4j.bolt.data.Neo4jBoltQueryResultColumn;
import com.neueda.jetbrains.plugin.graphdb.database.neo4j.bolt.data.Neo4jBoltQueryResultRow;
import org.neo4j.driver.v1.summary.InputPosition;
import org.neo4j.driver.v1.summary.Plan;
import org.neo4j.driver.v1.summary.ResultSummary;

import java.util.ArrayList;
Expand All @@ -18,6 +21,7 @@
import java.util.Optional;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

public class Neo4jBoltBuffer {

Expand Down Expand Up @@ -103,4 +107,39 @@ public List<GraphQueryNotification> getNotifications() {

return notifications;
}

public boolean hasPlan() {
return Optional.ofNullable(resultSummary)
.map(ResultSummary::hasPlan)
.orElse(false);
}

public boolean isProfilePlan() {
return Optional.ofNullable(resultSummary)
.map(ResultSummary::hasProfile)
.orElse(false);
}

public Optional<GraphQueryPlan> getQueryPlan() {
if (!hasPlan()) {
return Optional.empty();
}

Plan plan = resultSummary.plan();
return Optional.of(new Neo4jBoltQueryPlan(plan.operatorType(), getArguments(plan), plan.identifiers(),
getPlanChildren(plan.children())));
}

private static List<Neo4jBoltQueryPlan> getPlanChildren(List<? extends Plan> childrenPlans) {
return childrenPlans.stream()
.map(plan -> new Neo4jBoltQueryPlan(plan.operatorType(), getArguments(plan), plan.identifiers(),
getPlanChildren(plan.children())))
.collect(toList());
}

private static Map<String, Object> getArguments(Plan plan) {
return plan.arguments().entrySet().stream()
.collect(toMap(Map.Entry::getKey, e -> e.getValue().asObject()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.neueda.jetbrains.plugin.graphdb.database.neo4j.bolt.data;

import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryPlan;

import java.util.List;
import java.util.Map;

public class Neo4jBoltQueryPlan implements GraphQueryPlan {

private String operatorType;
private Map<String, Object> arguments;
private List<String> identifiers;
private List<Neo4jBoltQueryPlan> children;

public Neo4jBoltQueryPlan(String operatorType, Map<String, Object> arguments, List<String> identifiers,
List<Neo4jBoltQueryPlan> children) {
this.operatorType = operatorType;
this.arguments = arguments;
this.identifiers = identifiers;
this.children = children;
}

@Override
public String getOperatorType() {
return operatorType;
}

@Override
public Map<String, Object> getArguments() {
return arguments;
}

@Override
public List<String> getIdentifiers() {
return identifiers;
}

@Override
public List<Neo4jBoltQueryPlan> children() {
return children;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.neueda.jetbrains.plugin.graphdb.database.api.data.GraphNode;
import com.neueda.jetbrains.plugin.graphdb.database.api.data.GraphRelationship;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryNotification;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryPlan;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResult;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResultColumn;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResultRow;
Expand Down Expand Up @@ -149,6 +150,21 @@ public List<GraphQueryNotification> getNotifications() {
return buffer.getNotifications();
}

@Override
public boolean hasPlan() {
return buffer.hasPlan();
}

@Override
public boolean isProfilePlan() {
return buffer.isProfilePlan();
}

@Override
public Optional<GraphQueryPlan> getPlan() {
return buffer.getQueryPlan();
}

private Optional<GraphNode> findNodeById(List<GraphNode> nodes, String id) {
return nodes.stream().filter((node) -> node.getId().equals(id)).findFirst();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.analytics.Analytics;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.state.DataSourceApi;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.event.QueryExecutionProcessEvent;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.event.QueryPlanEvent;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.util.Notifier;

import java.util.concurrent.Future;
Expand Down Expand Up @@ -61,6 +62,11 @@ private synchronized void executeInBackground(DataSourceApi dataSource, ExecuteQ
event.resultReceived(payload, result);
event.postResultReceived(payload);
event.executionCompleted(payload);

if (result.hasPlan()) {
QueryPlanEvent queryPlanEvent = messageBus.syncPublisher(QueryPlanEvent.QUERY_PLAN_EVENT);
queryPlanEvent.queryPlanReceived(payload.getContent(), result);
}
});
} catch (Exception e) {
ApplicationManager.getApplication().invokeLater(() -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console;

import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
Expand All @@ -22,20 +26,34 @@
import com.intellij.ui.tabs.TabInfo;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.UIUtil;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResult;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.analytics.Analytics;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.event.QueryPlanEvent;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.graph.GraphPanel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.log.LogPanel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.params.ParametersPanel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.plan.QueryPlanPanel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.status.ExecutionStatusBarWidget;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.table.TablePanel;
import com.neueda.jetbrains.plugin.graphdb.platform.GraphConstants;
import com.neueda.jetbrains.plugin.graphdb.visualization.services.LookAndFeelService;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.concurrent.atomic.AtomicInteger;

import static java.time.temporal.ChronoField.*;

public class GraphConsoleView implements Disposable {

public static final String PROFILE_PLAN_TITLE = "Profile";
public static final String EXPLAIN_PLAN_TITLE = "Explain";
private boolean initialized;

private ExecutionStatusBarWidget executionStatusBarWidget;
Expand Down Expand Up @@ -66,6 +84,15 @@ public class GraphConsoleView implements Disposable {
private LogPanel logPanel;
private ParametersPanel parametersPanel;

private static final DateTimeFormatter QUERY_PLAN_TIME_FORMAT = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.toFormatter();

public GraphConsoleView() {
initialized = false;

Expand Down Expand Up @@ -106,6 +133,10 @@ public void initToolWindow(Project project, ToolWindow toolWindow) {
return callback;
});

AtomicInteger tabId = new AtomicInteger(0);
project.getMessageBus().connect().subscribe(QueryPlanEvent.QUERY_PLAN_EVENT,
(query, result) -> createNewQueryPlanTab(query, result, tabId.incrementAndGet()));

// Actions
final ActionGroup consoleActionGroup = (ActionGroup)
ActionManager.getInstance().getAction(GraphConstants.Actions.CONSOLE_ACTIONS);
Expand All @@ -123,6 +154,22 @@ private void createUIComponents() {
graphCanvas = new JPanel(new GridLayout(0, 1));
consoleTabsPane = new JBTabsPaneImpl(null, SwingConstants.TOP, this);
consoleTabs = (JBTabsImpl) consoleTabsPane.getTabs();

consoleTabs.addTabMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (UIUtil.isCloseClick(e, MouseEvent.MOUSE_RELEASED)) {
final TabInfo info = consoleTabs.findInfo(e);
if (info != null) {
String tabTitle = info.getText();
if (tabTitle.startsWith(PROFILE_PLAN_TITLE) || tabTitle.startsWith(EXPLAIN_PLAN_TITLE)) {
IdeEventQueue.getInstance().blockNextEvents(e);
consoleTabs.removeTab(info);
}
}
}
}
});
}

private void updateLookAndFeel() {
Expand All @@ -146,6 +193,29 @@ private void initializeWidgets(Project project) {
statusBar.addWidget(executionStatusBarWidget, "before Position");
}

private void createNewQueryPlanTab(String originalQuery,
GraphQueryResult result, int tabId) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout(0, 3));

QueryPlanPanel qpPanel = new QueryPlanPanel(originalQuery, result);
qpPanel.initialize(panel);

TabInfo tabInfo = new TabInfo(panel);
DefaultActionGroup tabActions = new DefaultActionGroup(new QueryPlanPanel.CloseTab() {
@Override
public void actionPerformed(AnActionEvent e) {
super.actionPerformed(e);
consoleTabs.removeTab(tabInfo);
}
});
tabInfo.setTabLabelActions(tabActions, ActionPlaces.EDITOR_TAB);

String planType = result.isProfilePlan() ? PROFILE_PLAN_TITLE : EXPLAIN_PLAN_TITLE;
consoleTabs.addTab(tabInfo.setText(String.format("%1s %2d - %3s", planType, tabId,
LocalDateTime.now().format(QUERY_PLAN_TIME_FORMAT))));
}

public TablePanel getTablePanel() {
return tablePanel;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.console.event;

import com.intellij.util.messages.Topic;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResult;

public interface QueryPlanEvent {

Topic<QueryPlanEvent> QUERY_PLAN_EVENT = Topic.create("GraphDatabaseConsole.QueryPlanEvent", QueryPlanEvent.class);

void queryPlanReceived(String query, GraphQueryResult result);
}
Loading