未验证 提交 8461dff4 编写于 作者: S Serge Rider 提交者: GitHub

Merge pull request #5898 from dbeaver/5005_MSSQL_Plan

5005 mssql plan
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2005/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2005"/>
<jxb:anonymousTypeName suffix="_sql2005"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2005sp2/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2005sp2"/>
<jxb:anonymousTypeName suffix="_sql2005sp2"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2008/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2008"/>
<jxb:anonymousTypeName suffix="_sql2008"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2012/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2012"/>
<jxb:anonymousTypeName suffix="_sql2012"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2014/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2014"/>
<jxb:anonymousTypeName suffix="_sql2014"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2014sp2/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2014sp2"/>
<jxb:anonymousTypeName suffix="_sql2014sp2"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2016/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2016"/>
<jxb:anonymousTypeName suffix="_sql2016"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2016sp1/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2016sp1"/>
<jxb:anonymousTypeName suffix="_sql2016sp1"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schemaLocation="../schemas/sql2017/showplanxml.xsd"
jxb:version="2.0">
<jxb:bindings node="//xsd:complexType[@name='ConvertType']/xsd:sequence/xsd:element[@name='Style']">
<jxb:property name="ConvertStyle"/>
</jxb:bindings>
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="_sql2017"/>
<jxb:anonymousTypeName suffix="_sql2017"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
\ No newline at end of file
set xjc="C:\Program Files\Java\jdk1.8.0_181\bin\xjc"
rmdir ./classes/* /s /q
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2017.xjb ./schemas/sql2017/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2016sp1 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2016sp1.xjb ./schemas/sql2016sp1/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2016 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2016.xjb ./schemas/sql2016/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2014sp2 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2014sp2.xjb ./schemas/sql2014sp2/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2014 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2014.xjb ./schemas/sql2014/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2012 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2012.xjb ./schemas/sql2012/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2008 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2008.xjb ./schemas/sql2008/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2005sp2 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2005sp2.xjb ./schemas/sql2005sp2/showplanxml.xsd
%xjc% -verbose -d ./classes/ -p org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2005 -npa -no-header -encoding UTF8 -enableIntrospection -disableXmlSecurity -b ./bindings/sql2005.xjb ./schemas/sql2005/showplanxml.xsd
\ No newline at end of file
......@@ -24,12 +24,14 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ModelPreferences;
import org.jkiss.dbeaver.ext.mssql.SQLServerConstants;
import org.jkiss.dbeaver.ext.mssql.SQLServerUtils;
import org.jkiss.dbeaver.ext.mssql.model.plan.SQLServerQueryPlanner;
import org.jkiss.dbeaver.ext.mssql.model.session.SQLServerSessionManager;
import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.admin.sessions.DBAServerSessionManager;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.exec.*;
import org.jkiss.dbeaver.model.exec.jdbc.*;
import org.jkiss.dbeaver.model.exec.plan.DBCQueryPlanner;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCDataSource;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCExecutionContext;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
......@@ -320,8 +322,10 @@ public class SQLServerDataSource extends JDBCDataSource implements DBSObjectSele
public <T> T getAdapter(Class<T> adapter) {
if (adapter == DBSStructureAssistant.class) {
return adapter.cast(new SQLServerStructureAssistant(this));
} else if (adapter == DBAServerSessionManager .class) {
} else if (adapter == DBAServerSessionManager.class) {
return adapter.cast(new SQLServerSessionManager(this));
} else if (adapter == DBCQueryPlanner.class) {
return adapter.cast(new SQLServerQueryPlanner(this));
}
return super.getAdapter(adapter);
}
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
* Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
*
* Licensed 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.jkiss.dbeaver.ext.mssql.model.plan;
import java.io.FileWriter;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode;
import org.jkiss.dbeaver.model.impl.plan.AbstractExecutionPlan;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.xml.XMLException;
public class SQLServerPlanAnalyzer extends AbstractExecutionPlan {
private static final String TURN_PLAN_ON = "SET STATISTICS XML ON";
private String query;
private List<DBCPlanNode> nodes;
private static final Log log = Log.getLog(SQLServerPlanAnalyzer.class);
public SQLServerPlanAnalyzer(String query) {
this.query = query;
}
@Override
public String getQueryString() {
return query;
}
@Override
public String getPlanQueryString() throws DBException {
return query;
}
@Override
public List<? extends DBCPlanNode> getPlanNodes(Map<String, Object> options) {
return nodes;
}
public void explain(DBCSession session) throws DBCException
{
JDBCSession connection = (JDBCSession) session;
boolean oldAutoCommit = false;
try {
oldAutoCommit = connection.getAutoCommit();
if (oldAutoCommit) {
connection.setAutoCommit(false);
}
try (JDBCStatement dbStat = connection.createStatement()) {
dbStat.execute(TURN_PLAN_ON);
try (JDBCResultSet dbResult = dbStat.executeQuery(query)) {
if (dbStat.getMoreResults()) {
try (JDBCResultSet planResult = dbStat.getResultSet()) {
if (planResult.next()) {
nodes = SQLServerPlanParser.getInstance().parse(planResult.getString(1),query);
} else {
throw new DBCException("Query plan not available");
}
}
} else {
throw new DBCException("Query plan not supported");
}
} catch (Exception e) {
throw new DBCException("Can't parse plan XML", e);
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getDataSource());
} finally {
// Rollback changes because EXPLAIN actually executes query and it could be INSERT/UPDATE
try {
connection.rollback();
if (oldAutoCommit) {
connection.setAutoCommit(true);
}
} catch (SQLException e) {
log.error("Error closing plan analyser", e);
}
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
* Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
*
* Licensed 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.jkiss.dbeaver.ext.mssql.model.plan;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.RelOpType_sql2017;
import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode;
import org.jkiss.dbeaver.model.impl.plan.AbstractExecutionPlanNode;
public class SQLServerPlanNode extends AbstractExecutionPlanNode {
private final RelOpType_sql2017 node;
private String name;
private final String type;
private final SQLServerPlanNode parent;
private final List<SQLServerPlanNode> nested = new ArrayList<>();
/*
@XmlAttribute(name = "Filtered")
protected Boolean filtered;
@XmlAttribute(name = "TableReferenceId")
protected Integer tableReferenceId;
@XmlAttribute(name = "CloneAccessScope")
protected CloneAccessScopeType_sql2017 cloneAccessScope;
@XmlAttribute(name = "Storage")
protected StorageType_sql2017 storage;
*/
public SQLServerPlanNode(String name, String type, RelOpType_sql2017 node,SQLServerPlanNode parent) {
this.name = name;
this.type = type;
this.parent = parent;
this.node = node;
}
@Override
public String getNodeName() {
return name;
}
@Override
public String getNodeType() {
return type;
}
@Override
public DBCPlanNode getParent() {
return parent;
}
@Override
public Collection<? extends DBCPlanNode> getNested() {
return nested;
}
public RelOpType_sql2017 getNode() {
return node;
}
public void addNested(SQLServerPlanNode node) {
nested.add(node);
}
@Override
public String toString() {
return "SQLServerPlanNode [name=" + name + ", type=" + type + "]";
}
public void setName(String name) {
this.name = name;
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
* Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
*
* Licensed 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.jkiss.dbeaver.ext.mssql.model.plan;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.BaseStmtInfoType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.CloneAccessScopeType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.IndexKindType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.ObjectType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.QueryPlanType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.RelOpBaseType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.RelOpType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.RowsetType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.ShowPlanXML;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.ShowPlanXML.BatchSequence_sql2017.Batch_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.StmtBlockType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.StmtSimpleType_sql2017;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.StorageType_sql2017;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode;
import org.xml.sax.InputSource;
public class SQLServerPlanParser {
public static final String rootNodeXPath = "/*[local-name() = 'ShowPlanXML']";
public static final String VERSION_ATTR = "Version";
private static final Log log = Log.getLog(SQLServerPlanParser.class);
private JAXBContext jaxbContext = null;
private Unmarshaller jaxbUnmarshaller = null;
public static SQLServerPlanParser instance = new SQLServerPlanParser();
private SQLServerPlanParser() {
}
public static SQLServerPlanParser getInstance() {
return instance;
}
private ShowPlanXML parseXML(String planString) throws JAXBException {
if (jaxbContext == null) {
jaxbContext = JAXBContext.newInstance(ShowPlanXML.class);
}
if (jaxbUnmarshaller == null) {
jaxbUnmarshaller = jaxbContext.createUnmarshaller();
}
return (ShowPlanXML) jaxbUnmarshaller.unmarshal(new InputSource(new StringReader(planString)));
}
private QueryPlanType_sql2017 findQueryPlan(ShowPlanXML plan, String query) {
for (Batch_sql2017 batch : plan.getBatchSequence().getBatch()) {
for (StmtBlockType_sql2017 stmt : batch.getStatements()) {
for (BaseStmtInfoType_sql2017 s : stmt.getStmtSimpleOrStmtCondOrStmtCursor()) {
if (s instanceof StmtSimpleType_sql2017) {
if (((StmtSimpleType_sql2017) s).getStatementText().equals(query.trim())) {
return ((StmtSimpleType_sql2017) s).getQueryPlan();
}
}
}
}
}
return null;
}
public List<Method> getAccessibleMethods(Class clazz) {
List<Method> result = new ArrayList<Method>();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers)) {
if (RelOpBaseType_sql2017.class.isAssignableFrom(method.getReturnType())) {
result.add(method);
}
}
}
clazz = clazz.getSuperclass();
}
return result;
}
private RowsetType_sql2017 findRowset(Object obj)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> clazz = obj.getClass();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers)) {
if (RowsetType_sql2017.class.isAssignableFrom(method.getReturnType())) {
RowsetType_sql2017 res = (RowsetType_sql2017) method.invoke(obj);
if (res != null) {
return res;
}
}
}
}
clazz = clazz.getSuperclass();
}
return null;
}
private List<RelOpType_sql2017> getRelOpChild(Object object) {
List<RelOpType_sql2017> child = new ArrayList<RelOpType_sql2017>();
try {
Method method = object.getClass().getMethod("getRelOp");
if (RelOpType_sql2017.class.isAssignableFrom(method.getReturnType())) {
child.add((RelOpType_sql2017) method.invoke(object));
} else if (List.class.isAssignableFrom(method.getReturnType())) {
child.addAll((List<RelOpType_sql2017>) method.invoke(object));
}
} catch (NoSuchMethodException ne) {
log.debug("Leaf node " + object.getClass());
} catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
log.debug("Ignored in getRelOp in " + object.getClass(), e);
}
return child;
}
private String parseObject(ObjectType_sql2017 o,SQLServerPlanNode planNode) {
StringBuilder sb = new StringBuilder();
if (o.getIndex() != null) {
if (o.getIndex() != null) {
sb.append(o.getIndex());
}
if (o.getIndexKind() != null) {
sb.append(" [").append(o.getIndexKind()).append("]");
}
sb.append(" ");
} else if (o.getTable() != null) {
if (o.getDatabase() != null) {
sb.append(o.getDatabase()).append(".");
}
if (o.getSchema() != null) {
sb.append(o.getSchema()).append(".");
}
if (o.getTable() != null) {
sb.append(o.getTable());
}
if (o.getAlias() != null) {
sb.append(" ").append(o.getAlias());
}
sb.append(" ");
} else {
return "";
}
return sb.toString();
}
private void setObjectName(Object obj,SQLServerPlanNode planNode) {
final StringBuilder sb = new StringBuilder();
try {
RowsetType_sql2017 rowset = findRowset(obj);
if (rowset == null) {
return ;
}
rowset.getObject().stream().forEach(o -> {
sb.append(parseObject(o,planNode));
if (sb.length() > 0) {
sb.append(" ");
}
});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
log.debug(obj.getClass().getName() + " has no name");
return ;
}
planNode.setName(sb.toString());
}
private void addChilds(SQLServerPlanNode nodeParent)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
List<RelOpType_sql2017> childs = getChilds(nodeParent.getNode());
for (RelOpType_sql2017 child : childs) {
if (child != null) {
SQLServerPlanNode node = new SQLServerPlanNode("", child.getLogicalOp().value(),
child, nodeParent);
setObjectName(child,node);
nodeParent.addNested(node);
addChilds(node);
}
}
}
private List<RelOpType_sql2017> getChilds(RelOpType_sql2017 node)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
List<RelOpType_sql2017> childs = new ArrayList<>();
List<Method> allChildMethods = getAccessibleMethods(node.getClass());
for (Method method : allChildMethods) {
Object result = method.invoke(node);
if (result != null) {
childs.addAll(getRelOpChild(result));
}
}
return childs;
}
public List<DBCPlanNode> parse(String planString, String sqlString) throws DBCException {
List<DBCPlanNode> nodes = new ArrayList<>();
try {
ShowPlanXML plan = parseXML(planString);
QueryPlanType_sql2017 queryPlan = findQueryPlan(plan, sqlString);
if (queryPlan == null) {
throw new DBCException("Unable to find plan");
}
RelOpType_sql2017 relOpRoot = queryPlan.getRelOp();
SQLServerPlanNode root = new SQLServerPlanNode("",
relOpRoot.getLogicalOp().value(), relOpRoot, null);
setObjectName(relOpRoot,root);
addChilds(root);
nodes.add(root);
return nodes;
} catch (JAXBException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new DBCException("Error parsing plan", e);
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
* Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
*
* Licensed 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.jkiss.dbeaver.ext.mssql.model.plan.meta;
import org.jkiss.dbeaver.ext.mssql.model.plan.schemas.sql2017.RelOpType_sql2017;
public interface SQLServerRelNode {
RelOpType_sql2017 getRelOp();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册