提交 900c250d 编写于 作者: S serge-rider

Explain plan UI refactoring

上级 ac2f7e7a
...@@ -64,8 +64,8 @@ import org.jkiss.dbeaver.ui.controls.itemlist.DatabaseObjectListControl; ...@@ -64,8 +64,8 @@ import org.jkiss.dbeaver.ui.controls.itemlist.DatabaseObjectListControl;
import org.jkiss.dbeaver.ui.editors.StringEditorInput; import org.jkiss.dbeaver.ui.editors.StringEditorInput;
import org.jkiss.dbeaver.ui.editors.SubEditorSite; import org.jkiss.dbeaver.ui.editors.SubEditorSite;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditorBase; import org.jkiss.dbeaver.ui.editors.sql.SQLEditorBase;
import org.jkiss.dbeaver.ui.properties.PropertyTreeViewer;
import org.jkiss.dbeaver.ui.editors.sql.plan.simple.PlanNodesTree; import org.jkiss.dbeaver.ui.editors.sql.plan.simple.PlanNodesTree;
import org.jkiss.dbeaver.ui.properties.PropertyTreeViewer;
import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.CommonUtils; import org.jkiss.utils.CommonUtils;
...@@ -243,8 +243,7 @@ public class SessionManagerViewer<SESSION_TYPE extends DBAServerSession> ...@@ -243,8 +243,7 @@ public class SessionManagerViewer<SESSION_TYPE extends DBAServerSession>
String sqlText = curSession == null ? "" : CommonUtils.notEmpty(curSession.getActiveQuery()); String sqlText = curSession == null ? "" : CommonUtils.notEmpty(curSession.getActiveQuery());
if (!CommonUtils.isEmpty(sqlText)) { if (!CommonUtils.isEmpty(sqlText)) {
DBPDataSource dataSource = sessionManager.getDataSource(); DBPDataSource dataSource = sessionManager.getDataSource();
planTree.init(DBUtils.getDefaultContext(dataSource, false), planner, sqlText); planTree.showPlan(dataSource, null);
planTree.loadData();
} }
} }
if (detailsFolder.getSelectionIndex() > 0) { if (detailsFolder.getSelectionIndex() > 0) {
......
...@@ -1455,7 +1455,7 @@ public class SQLEditor extends SQLEditorBase implements ...@@ -1455,7 +1455,7 @@ public class SQLEditor extends SQLEditorBase implements
} }
if (planView == null) { if (planView == null) {
planView = new ExplainPlanViewer(this, resultTabs); planView = new ExplainPlanViewer(this, this, resultTabs);
final CTabItem item = new CTabItem(resultTabs, SWT.CLOSE); final CTabItem item = new CTabItem(resultTabs, SWT.CLOSE);
item.setControl(planView.getControl()); item.setControl(planView.getControl());
...@@ -1469,7 +1469,7 @@ public class SQLEditor extends SQLEditorBase implements ...@@ -1469,7 +1469,7 @@ public class SQLEditor extends SQLEditorBase implements
} }
try { try {
planView.explainQueryPlan(getExecutionContext(), sqlQuery); planView.explainQueryPlan(sqlQuery);
} catch (DBCException e) { } catch (DBCException e) {
DBWorkbench.getPlatformUI().showError( DBWorkbench.getPlatformUI().showError(
SQLEditorMessages.editors_sql_error_execution_plan_title, SQLEditorMessages.editors_sql_error_execution_plan_title,
......
...@@ -21,6 +21,7 @@ import org.eclipse.swt.widgets.Composite; ...@@ -21,6 +21,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPart;
import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext; import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.plan.DBCPlan;
import org.jkiss.dbeaver.model.sql.SQLQuery; import org.jkiss.dbeaver.model.sql.SQLQuery;
/** /**
...@@ -30,6 +31,6 @@ public interface SQLPlanViewer { ...@@ -30,6 +31,6 @@ public interface SQLPlanViewer {
Viewer createPlanViewer(IWorkbenchPart workbenchPart, Composite parent); Viewer createPlanViewer(IWorkbenchPart workbenchPart, Composite parent);
void explainQueryPlan(Viewer viewer, DBCExecutionContext executionContext, SQLQuery query) throws DBCException; void visualizeQueryPlan(Viewer viewer, SQLQuery query, DBCPlan plan);
} }
...@@ -27,8 +27,15 @@ import org.eclipse.swt.widgets.Control; ...@@ -27,8 +27,15 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPart;
import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPContextProvider;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext; import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.DBCExecutionPurpose;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.exec.plan.DBCPlan;
import org.jkiss.dbeaver.model.exec.plan.DBCQueryPlanner;
import org.jkiss.dbeaver.model.sql.SQLQuery; import org.jkiss.dbeaver.model.sql.SQLQuery;
import org.jkiss.dbeaver.runtime.DBWorkbench; import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.ui.DBeaverIcons; import org.jkiss.dbeaver.ui.DBeaverIcons;
...@@ -41,6 +48,8 @@ import org.jkiss.dbeaver.ui.editors.sql.plan.registry.SQLPlanViewDescriptor; ...@@ -41,6 +48,8 @@ import org.jkiss.dbeaver.ui.editors.sql.plan.registry.SQLPlanViewDescriptor;
import org.jkiss.dbeaver.ui.editors.sql.plan.registry.SQLPlanViewRegistry; import org.jkiss.dbeaver.ui.editors.sql.plan.registry.SQLPlanViewRegistry;
import org.jkiss.utils.CommonUtils; import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
/** /**
* ResultSetViewer * ResultSetViewer
*/ */
...@@ -49,6 +58,7 @@ public class ExplainPlanViewer extends Viewer ...@@ -49,6 +58,7 @@ public class ExplainPlanViewer extends Viewer
static final Log log = Log.getLog(ExplainPlanViewer.class); static final Log log = Log.getLog(ExplainPlanViewer.class);
private final IWorkbenchPart workbenchPart; private final IWorkbenchPart workbenchPart;
private final DBPContextProvider contextProvider;
private final Composite planPresentationContainer; private final Composite planPresentationContainer;
private final VerticalFolder tabViewFolder; private final VerticalFolder tabViewFolder;
private final Composite planViewComposite; private final Composite planViewComposite;
...@@ -66,9 +76,10 @@ public class ExplainPlanViewer extends Viewer ...@@ -66,9 +76,10 @@ public class ExplainPlanViewer extends Viewer
private PlanViewInfo activeViewInfo; private PlanViewInfo activeViewInfo;
private SQLQuery lastQuery; private SQLQuery lastQuery;
public ExplainPlanViewer(final IWorkbenchPart workbenchPart, Composite parent) public ExplainPlanViewer(final IWorkbenchPart workbenchPart, DBPContextProvider contextProvider, Composite parent)
{ {
this.workbenchPart = workbenchPart; this.workbenchPart = workbenchPart;
this.contextProvider = contextProvider;
planPresentationContainer = UIUtils.createPlaceholder(parent, 2); planPresentationContainer = UIUtils.createPlaceholder(parent, 2);
planPresentationContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); planPresentationContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
...@@ -121,13 +132,10 @@ public class ExplainPlanViewer extends Viewer ...@@ -121,13 +132,10 @@ public class ExplainPlanViewer extends Viewer
return lastQuery; return lastQuery;
} }
public void explainQueryPlan(DBCExecutionContext executionContext, SQLQuery query) throws DBCException { public void explainQueryPlan(SQLQuery query) throws DBCException {
this.lastQuery = query; this.lastQuery = query;
for (PlanViewInfo viewInfo : getPlanViews()) {
if (viewInfo.viewer != null) { refresh();
viewInfo.planViewer.explainQueryPlan(viewInfo.viewer, executionContext, query);
}
}
} }
private PlanViewInfo[] getPlanViews() { private PlanViewInfo[] getPlanViews() {
...@@ -180,8 +188,40 @@ public class ExplainPlanViewer extends Viewer ...@@ -180,8 +188,40 @@ public class ExplainPlanViewer extends Viewer
@Override @Override
public void refresh() { public void refresh() {
if (activeViewInfo != null) { DBCQueryPlanner planner;
activeViewInfo.viewer.refresh(); DBCExecutionContext executionContext = contextProvider.getExecutionContext();
if (executionContext != null) {
DBPDataSource dataSource = executionContext.getDataSource();
planner = DBUtils.getAdapter(DBCQueryPlanner.class, dataSource);
} else {
planner = null;
}
if (planner == null) {
DBWorkbench.getPlatformUI().showError("No SQL Plan","This datasource doesn't support execution plans");
} else {
try {
UIUtils.runInProgressDialog(monitor -> {
try {
try (DBCSession session = executionContext.openSession(monitor, DBCExecutionPurpose.UTIL, "Explain '" + lastQuery.getText() + "'")) {
DBCPlan plan = planner.planQueryExecution(session, lastQuery.getText());
UIUtils.asyncExec(() -> visualizePlan(plan));
}
} catch (Throwable ex) {
throw new InvocationTargetException(ex);
}
});
} catch (InvocationTargetException e) {
DBWorkbench.getPlatformUI().showError("Explain Plan error","Error explaining SQL execution plan", e.getTargetException());
}
}
}
private void visualizePlan(DBCPlan plan) {
for (PlanViewInfo viewInfo : getPlanViews()) {
if (viewInfo.viewer != null) {
viewInfo.planViewer.visualizeQueryPlan(viewInfo.viewer, lastQuery, plan);
}
} }
} }
......
...@@ -22,22 +22,17 @@ import org.eclipse.jface.viewers.Viewer; ...@@ -22,22 +22,17 @@ import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchSite; import org.eclipse.ui.IWorkbenchSite;
import org.jkiss.code.NotNull; import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext; import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.exec.DBCExecutionPurpose;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.exec.plan.DBCPlan; import org.jkiss.dbeaver.model.exec.plan.DBCPlan;
import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode; import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode;
import org.jkiss.dbeaver.model.exec.plan.DBCQueryPlanner;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.load.DatabaseLoadService;
import org.jkiss.dbeaver.model.struct.DBSObject; import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.ui.LoadingJob; import org.jkiss.dbeaver.ui.LoadingJob;
import org.jkiss.dbeaver.ui.navigator.actions.NavigatorHandlerObjectOpen;
import org.jkiss.dbeaver.ui.controls.ObjectViewerRenderer; import org.jkiss.dbeaver.ui.controls.ObjectViewerRenderer;
import org.jkiss.dbeaver.ui.controls.itemlist.DatabaseObjectListControl; import org.jkiss.dbeaver.ui.controls.itemlist.DatabaseObjectListControl;
import org.jkiss.dbeaver.ui.navigator.actions.NavigatorHandlerObjectOpen;
import org.jkiss.utils.CommonUtils; import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
...@@ -46,9 +41,8 @@ import java.util.List; ...@@ -46,9 +41,8 @@ import java.util.List;
*/ */
public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> { public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> {
private DBCExecutionContext context;
private DBCQueryPlanner planner;
private String query; private String query;
private DBPDataSource dataSource;
public PlanNodesTree(Composite parent, int style, IWorkbenchSite site) public PlanNodesTree(Composite parent, int style, IWorkbenchSite site)
{ {
...@@ -65,27 +59,29 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> { ...@@ -65,27 +59,29 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> {
@NotNull @NotNull
@Override @Override
protected String getListConfigId(List<Class<?>> classList) { protected String getListConfigId(List<Class<?>> classList) {
return "ExecutionPlan/" + context.getDataSource().getContainer().getDriver().getId(); return "ExecutionPlan/" + dataSource.getContainer().getDriver().getId();
} }
@Override @Override
protected LoadingJob<Collection<DBCPlanNode>> createLoadService() protected LoadingJob<Collection<DBCPlanNode>> createLoadService()
{ {
return LoadingJob.createService( return null;
new ExplainPlanService(),
new PlanLoadVisualizer());
} }
public boolean isInitialized() public void showPlan(DBPDataSource dataSource, DBCPlan plan) {
{ this.dataSource = dataSource;
return planner != null; List<DBCPlanNode> nodes = new ArrayList<>(plan.getPlanNodes());
}
final TreeViewer itemsViewer = (TreeViewer) PlanNodesTree.this.getItemsViewer();
itemsViewer.getControl().setRedraw(false);
try {
clearListData();
setListData(nodes, false);
itemsViewer.expandToLevel(10);
} finally {
itemsViewer.getControl().setRedraw(true);
}
public void init(DBCExecutionContext context, DBCQueryPlanner planner, String query)
{
this.context = context;
this.planner = planner;
this.query = query;
} }
private static ITreeContentProvider CONTENT_PROVIDER = new ITreeContentProvider() { private static ITreeContentProvider CONTENT_PROVIDER = new ITreeContentProvider() {
...@@ -135,11 +131,19 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> { ...@@ -135,11 +131,19 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> {
}; };
private class ExplainPlanService extends DatabaseLoadService<Collection<DBCPlanNode>> { /*
public static class ExplainPlanService extends DatabaseLoadService<Collection<DBCPlanNode>> {
private final DBCQueryPlanner planner;
private final DBCExecutionContext executionContext;
private final String query;
protected ExplainPlanService() protected ExplainPlanService(DBCQueryPlanner planner, DBCExecutionContext executionContext, String query)
{ {
super("Explain plan", planner.getDataSource()); super("Explain plan", planner.getDataSource());
this.planner = planner;
this.executionContext = executionContext;
this.query = query;
} }
@Override @Override
...@@ -147,7 +151,7 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> { ...@@ -147,7 +151,7 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> {
throws InvocationTargetException, InterruptedException throws InvocationTargetException, InterruptedException
{ {
try { try {
try (DBCSession session = context.openSession(monitor, DBCExecutionPurpose.UTIL, "Explain '" + query + "'")) { try (DBCSession session = executionContext.openSession(monitor, DBCExecutionPurpose.UTIL, "Explain '" + query + "'")) {
DBCPlan plan = planner.planQueryExecution(session, query); DBCPlan plan = planner.planQueryExecution(session, query);
return (Collection<DBCPlanNode>) plan.getPlanNodes(); return (Collection<DBCPlanNode>) plan.getPlanNodes();
} }
...@@ -172,6 +176,7 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> { ...@@ -172,6 +176,7 @@ public class PlanNodesTree extends DatabaseObjectListControl<DBCPlanNode> {
} }
} }
} }
*/
private class PlanTreeRenderer extends ViewerRenderer { private class PlanTreeRenderer extends ViewerRenderer {
@Override @Override
......
...@@ -31,11 +31,7 @@ import org.eclipse.swt.widgets.Composite; ...@@ -31,11 +31,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPart;
import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.exec.plan.DBCPlan;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.plan.DBCQueryPlanner;
import org.jkiss.dbeaver.model.sql.SQLQuery; import org.jkiss.dbeaver.model.sql.SQLQuery;
import org.jkiss.dbeaver.runtime.properties.PropertyCollector; import org.jkiss.dbeaver.runtime.properties.PropertyCollector;
import org.jkiss.dbeaver.ui.ActionUtils; import org.jkiss.dbeaver.ui.ActionUtils;
...@@ -59,7 +55,6 @@ public class SQLPlanTreeViewer extends Viewer ...@@ -59,7 +55,6 @@ public class SQLPlanTreeViewer extends Viewer
private PropertyTreeViewer planProperties; private PropertyTreeViewer planProperties;
private SQLQuery query; private SQLQuery query;
private DBCQueryPlanner planner;
private RefreshPlanAction refreshPlanAction; private RefreshPlanAction refreshPlanAction;
private ToggleViewAction toggleViewAction; private ToggleViewAction toggleViewAction;
private final SashForm leftPanel; private final SashForm leftPanel;
...@@ -113,10 +108,9 @@ public class SQLPlanTreeViewer extends Viewer ...@@ -113,10 +108,9 @@ public class SQLPlanTreeViewer extends Viewer
planTree.getControl().addPaintListener(e -> { planTree.getControl().addPaintListener(e -> {
String message = null; String message = null;
if (planner == null) { if (query == null) {
message = "No connection or data source doesn't support execution plan"; message = "No connection or data source doesn't support execution plan";
} else if (CommonUtils.isEmpty(sqlText.getText())) { } else if (CommonUtils.isEmpty(sqlText.getText())) {
message = "Select a query and run " + ActionUtils.findCommandDescription( message = "Select a query and run " + ActionUtils.findCommandDescription(
SQLEditorCommands.CMD_EXPLAIN_PLAN, SQLEditorCommands.CMD_EXPLAIN_PLAN,
workbenchPart.getSite(), false); workbenchPart.getSite(), false);
...@@ -178,6 +172,7 @@ public class SQLPlanTreeViewer extends Viewer ...@@ -178,6 +172,7 @@ public class SQLPlanTreeViewer extends Viewer
{ {
return planTree.getItemsViewer(); return planTree.getItemsViewer();
} }
/*
public void explainQueryPlan(DBCExecutionContext executionContext, SQLQuery query) throws DBCException public void explainQueryPlan(DBCExecutionContext executionContext, SQLQuery query) throws DBCException
{ {
...@@ -209,6 +204,7 @@ public class SQLPlanTreeViewer extends Viewer ...@@ -209,6 +204,7 @@ public class SQLPlanTreeViewer extends Viewer
refreshPlanAction.setEnabled(true); refreshPlanAction.setEnabled(true);
toggleViewAction.setEnabled(true); toggleViewAction.setEnabled(true);
} }
*/
///////////////////////////////////////////////// /////////////////////////////////////////////////
// Viewer // Viewer
...@@ -238,6 +234,12 @@ public class SQLPlanTreeViewer extends Viewer ...@@ -238,6 +234,12 @@ public class SQLPlanTreeViewer extends Viewer
} }
public void showPlan(SQLQuery query, DBCPlan plan) {
this.query = query;
this.sqlText.setText(query.getText());
planTree.showPlan(query.getDataSource(), plan);
}
///////////////////////////////////////////////// /////////////////////////////////////////////////
// Actions // Actions
......
...@@ -21,6 +21,7 @@ import org.eclipse.swt.widgets.Composite; ...@@ -21,6 +21,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPart;
import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext; import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.plan.DBCPlan;
import org.jkiss.dbeaver.model.sql.SQLQuery; import org.jkiss.dbeaver.model.sql.SQLQuery;
import org.jkiss.dbeaver.ui.editors.sql.SQLPlanViewer; import org.jkiss.dbeaver.ui.editors.sql.SQLPlanViewer;
...@@ -37,8 +38,9 @@ public class SQLPlanViewerSimple implements SQLPlanViewer { ...@@ -37,8 +38,9 @@ public class SQLPlanViewerSimple implements SQLPlanViewer {
} }
@Override @Override
public void explainQueryPlan(Viewer viewer, DBCExecutionContext executionContext, SQLQuery query) throws DBCException { public void visualizeQueryPlan(Viewer viewer, SQLQuery query, DBCPlan plan) {
SQLPlanTreeViewer treeViewer = (SQLPlanTreeViewer) viewer; SQLPlanTreeViewer treeViewer = (SQLPlanTreeViewer) viewer;
treeViewer.explainQueryPlan(executionContext, query); treeViewer.showPlan(query, plan);
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册