// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package net.sourceforge.sqlexplorer.oracle.actions;
/**
* DOC qzhang class global comment. Detailled comment <br/>
*
* $Id: talend.epf 1 2006-09-29 17:06:40Z qzhang $
*
*/
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import net.sourceforge.sqlexplorer.Messages;
import net.sourceforge.sqlexplorer.oracle.actions.explain.ExplainNode;
import net.sourceforge.sqlexplorer.oracle.actions.explain.ExplainPlanActionGroup;
import net.sourceforge.sqlexplorer.parsers.Query;
import net.sourceforge.sqlexplorer.parsers.QueryParser;
import net.sourceforge.sqlexplorer.plugin.SQLExplorerPlugin;
import net.sourceforge.sqlexplorer.plugin.editors.SQLEditor;
import net.sourceforge.sqlexplorer.sqleditor.results.ResultsTab;
import net.sourceforge.sqlexplorer.sqlpanel.AbstractSQLExecution;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableTreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
public class ExplainExecution extends AbstractSQLExecution {
static class TreeLabelProvider extends LabelProvider implements ITableLabelProvider {
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
ExplainNode en = (ExplainNode) element;
if (columnIndex == 0)
return en.toString();
if (columnIndex == 1) {
int cost = en.getCost();
if (cost != -1)
return (new StringBuilder()).append(cost).toString();
else
return "";
}
if (columnIndex == 2) {
int card = en.getCardinality();
if (card != -1)
return (new StringBuilder()).append(card).toString();
else
return "";
} else {
return "";
}
}
TreeLabelProvider() {
}
}
public ExplainExecution(SQLEditor editor, QueryParser queryParser) {
super(editor, queryParser);
setProgressMessage(Messages.getString("SQLResultsView.ConnectionWait"));
}
private void displayResults(final ExplainNode node, final Query query) {
getEditor().getSite().getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
ResultsTab resultsTab = allocateResultsTab(query);
try {
Composite composite = resultsTab.getParent();
GridLayout gLayout = new GridLayout();
gLayout.numColumns = 2;
gLayout.marginLeft = 0;
gLayout.horizontalSpacing = 0;
gLayout.verticalSpacing = 0;
gLayout.marginWidth = 0;
gLayout.marginHeight = 0;
composite.setLayout(gLayout);
composite.setData("parenttab", resultsTab.getTabItem());
Composite pp = new Composite(composite, 0);
pp.setLayout(new FillLayout());
pp.setLayoutData(new GridData(1808));
TableTreeViewer tv = new TableTreeViewer(pp, 0x10800);
Table table = tv.getTableTree().getTable();
table.setLinesVisible(true);
table.setHeaderVisible(true);
TableColumn tc = new TableColumn(table, 0);
tc.setText("");
tc = new TableColumn(table, 0);
tc.setText("Cost");
tc = new TableColumn(table, 0);
tc.setText("Cardinality");
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnWeightData(6, 150, true));
tableLayout.addColumnData(new ColumnWeightData(1, 50, true));
tableLayout.addColumnData(new ColumnWeightData(1, 50, true));
table.setLayout(tableLayout);
tv.setContentProvider(new ITreeContentProvider() {
public void dispose() {
}
public Object[] getChildren(Object parentElement) {
return ((ExplainNode) parentElement).getChildren();
}
public Object[] getElements(Object inputElement) {
ExplainNode nd = (ExplainNode) inputElement;
return nd.getChildren();
}
public Object getParent(Object element) {
return ((ExplainNode) element).getParent();
}
public boolean hasChildren(Object element) {
return ((ExplainNode) element).getChildren().length > 0;
}
public void inputChanged(Viewer viewer1, Object obj, Object obj1) {
}
});
tv.setLabelProvider(new TreeLabelProvider() {
});
tv.setInput(node);
tv.refresh();
tv.expandAll();
for (int i = 0; i < table.getColumnCount(); i++)
table.getColumn(i).pack();
final ExplainPlanActionGroup actionGroup = new ExplainPlanActionGroup(tv, node.getChildren()[0]);
MenuManager menuManager = new MenuManager("ExplainPlanContextMenu");
menuManager.setRemoveAllWhenShown(true);
org.eclipse.swt.widgets.Menu contextMenu = menuManager.createContextMenu(table);
tv.getControl().setMenu(contextMenu);
menuManager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
actionGroup.fillContextMenu(manager);
}
});
composite.layout();
composite.redraw();
} catch (Exception e) {
if (resultsTab != null) {
Composite composite = resultsTab.getParent();
String message = e.getMessage();
Label errorLabel = new Label(composite, 4);
errorLabel.setText(message);
errorLabel.setLayoutData(new GridData(4, 128, true, false));
}
SQLExplorerPlugin.error("Error creating explain tab", e);
}
}
});
}
protected void doExecution(IProgressMonitor monitor) throws Exception {
int numErrors;
SQLException lastSQLException;
Query query;
numErrors = 0;
lastSQLException = null;
query = null;
Iterator iter = getQueryParser().iterator();
String id_;
query = (Query) iter.next();
if (monitor.isCanceled()) {
return;
}
_stmt = _connection.createStatement();
id_ = Integer.toHexString((new Random()).nextInt()).toUpperCase();
_stmt.execute((new StringBuilder("delete plan_table where statement_id='")).append(id_).append("'").toString());
_stmt.close();
_stmt = null;
if (monitor.isCanceled())
return;
ResultSet rs;
ExplainNode nd_parent;
try {
_stmt = _connection.createStatement();
_stmt.execute((new StringBuilder("EXPLAIN PLAN SET statement_id = '")).append(id_).append("' FOR ").append(
query.getQuerySql()).toString());
_stmt.close();
_stmt = null;
if (monitor.isCanceled())
return;
} catch (SQLException e) {
debugLogQuery(query, e);
boolean stopOnError = SQLExplorerPlugin.getDefault().getPreferenceStore().getBoolean("SQLEditor.StopOnError");
logException(e, query, stopOnError);
closeStatements();
if (stopOnError)
throw e;
numErrors++;
lastSQLException = e;
} catch (Exception e) {
closeStatements();
throw e;
}
_prepStmt = _connection
.prepareStatement("select level, object_type,operation,options,object_owner,object_name,optimizer,cardinality ,cost,id,parent_id,level from plan_table start with id = 0 and statement_id=? connect by prior id=parent_id and statement_id=?");
_prepStmt.setString(1, id_);
_prepStmt.setString(2, id_);
rs = _prepStmt.executeQuery();
if (monitor.isCanceled())
return;
HashMap mp = new HashMap();
int level;
ExplainNode nd;
for (; rs.next(); nd.setLevel(level)) {
String object_type = rs.getString("object_type");
String operation = rs.getString("operation");
String options = rs.getString("options");
String object_owner = rs.getString("object_owner");
String object_name = rs.getString("object_name");
String optimizer = rs.getString("optimizer");
int cardinality = rs.getInt("cardinality");
if (rs.wasNull())
cardinality = -1;
int cost = rs.getInt("cost");
if (rs.wasNull())
cost = -1;
int parentID = rs.getInt("parent_id");
int id = rs.getInt("id");
level = rs.getInt("level");
nd = null;
if (id == 0) {
ExplainNode dummy = new ExplainNode(null);
mp.put(new Integer(-1), dummy);
dummy.setId(-1);
nd = new ExplainNode(dummy);
dummy.add(nd);
nd.setId(0);
mp.put(new Integer(0), nd);
} else {
nd_parent = (ExplainNode) mp.get(new Integer(parentID));
nd = new ExplainNode(nd_parent);
nd_parent.add(nd);
mp.put(new Integer(id), nd);
}
nd.setCardinality(cardinality);
nd.setCost(cost);
nd.setObject_name(object_name);
nd.setObject_owner(object_owner);
nd.setObject_type(object_type);
nd.setOperation(operation);
nd.setOptimizer(optimizer);
nd.setOptions(options);
nd.setId(id);
}
rs.close();
_prepStmt.close();
_prepStmt = null;
nd_parent = (ExplainNode) mp.get(new Integer(-1));
if (monitor.isCanceled())
return;
displayResults(nd_parent, query);
debugLogQuery(query, null);
query = null;
if (numErrors == 1)
throw lastSQLException;
if (numErrors > 1)
MessageDialog.openError(getEditor().getSite().getShell(), "SQL Error",
"One or more of your SQL statements failed - check the Messages log for details");
return;
}
private void closeStatements() {
if (_stmt != null)
try {
_stmt.close();
_stmt = null;
} catch (Exception e) {
SQLExplorerPlugin.error("Error closing statement.", e);
}
if (_prepStmt != null)
try {
_prepStmt.close();
_prepStmt = null;
} catch (Exception e) {
SQLExplorerPlugin.error("Error closing statement.", e);
}
}
protected void doStop() throws Exception {
Exception t = null;
if (_stmt != null) {
try {
_stmt.cancel();
} catch (Exception e) {
t = e;
SQLExplorerPlugin.error("Error cancelling statement.", e);
}
try {
_stmt.close();
_stmt = null;
} catch (Exception e) {
SQLExplorerPlugin.error("Error closing statement.", e);
}
}
if (_prepStmt != null) {
try {
_prepStmt.cancel();
} catch (Exception e) {
t = e;
SQLExplorerPlugin.error("Error cancelling statement.", e);
}
try {
_prepStmt.close();
_prepStmt = null;
} catch (Exception e) {
SQLExplorerPlugin.error("Error closing statement.", e);
}
}
if (t != null)
throw t;
else
return;
}
private PreparedStatement _prepStmt;
private Statement _stmt;
}