/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * 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.oracle.model.plan; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.ext.oracle.model.OracleDataSource; import org.jkiss.dbeaver.ext.oracle.model.OracleObjectType; import org.jkiss.dbeaver.ext.oracle.model.OracleTablePhysical; import org.jkiss.dbeaver.model.exec.plan.DBCPlanNode; import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils; import org.jkiss.dbeaver.model.meta.Property; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.utils.CommonUtils; import org.jkiss.utils.IntKeyMap; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Oracle execution plan node */ public class OraclePlanNode implements DBCPlanNode { private final OracleDataSource dataSource; private String statementId; private long plan_id; private Timestamp timestamp; private String remarks; private String operation; private String options; private String objectNode; private String objectOwner; private String objectName; private String objectAlias; private long objectInstance; private String objectType; private String optimizer; private long searchColumns; private int id; private int parentId; private int depth; private int position; private long cost; private long cardinality; private long bytes; private String otherTag; private String partitionStart; private String partitionStop; private long partitionId; private String other; private String distribution; private long cpuCost; private long ioCost; private long tempSpace; private String accessPredicates; private String filterPredicates; private String projection; private long time; private String qblockName; private String otherXml; private OraclePlanNode parent; private List<OraclePlanNode> nested; public OraclePlanNode(OracleDataSource dataSource, IntKeyMap<OraclePlanNode> prevNodes, ResultSet dbResult) throws SQLException { this.dataSource = dataSource; this.statementId = JDBCUtils.safeGetString(dbResult, "statement_id"); this.plan_id = JDBCUtils.safeGetLong(dbResult, "plan_id"); this.timestamp = JDBCUtils.safeGetTimestamp(dbResult, "timestamp"); this.remarks = JDBCUtils.safeGetString(dbResult, "remarks"); this.operation = JDBCUtils.safeGetString(dbResult, "operation"); this.options = JDBCUtils.safeGetString(dbResult, "options"); this.objectNode = JDBCUtils.safeGetString(dbResult, "object_node"); this.objectOwner = JDBCUtils.safeGetString(dbResult, "object_owner"); this.objectName = JDBCUtils.safeGetString(dbResult, "object_name"); this.objectAlias = JDBCUtils.safeGetString(dbResult, "object_alias"); this.objectInstance = JDBCUtils.safeGetLong(dbResult, "object_instance"); this.objectType = JDBCUtils.safeGetString(dbResult, "object_type"); this.optimizer = JDBCUtils.safeGetString(dbResult, "optimizer"); this.searchColumns = JDBCUtils.safeGetLong(dbResult, "search_columns"); this.id = JDBCUtils.safeGetInt(dbResult, "id"); this.depth = JDBCUtils.safeGetInt(dbResult, "depth"); this.position = JDBCUtils.safeGetInt(dbResult, "position"); this.cost = JDBCUtils.safeGetLong(dbResult, "cost"); this.cardinality = JDBCUtils.safeGetLong(dbResult, "cardinality"); this.bytes = JDBCUtils.safeGetLong(dbResult, "bytes"); this.otherTag = JDBCUtils.safeGetString(dbResult, "other_tag"); this.partitionStart = JDBCUtils.safeGetString(dbResult, "partition_start"); this.partitionStop = JDBCUtils.safeGetString(dbResult, "partition_stop"); this.partitionId = JDBCUtils.safeGetLong(dbResult, "partition_id"); this.other = JDBCUtils.safeGetString(dbResult, "other"); this.distribution = JDBCUtils.safeGetString(dbResult, "distribution"); this.cpuCost = JDBCUtils.safeGetLong(dbResult, "cpu_cost"); this.ioCost = JDBCUtils.safeGetLong(dbResult, "io_cost"); this.tempSpace = JDBCUtils.safeGetLong(dbResult, "temp_space"); this.accessPredicates = JDBCUtils.safeGetString(dbResult, "access_predicates"); this.filterPredicates = JDBCUtils.safeGetString(dbResult, "filter_predicates"); this.projection = JDBCUtils.safeGetString(dbResult, "projection"); this.time = JDBCUtils.safeGetLong(dbResult, "time"); this.qblockName = JDBCUtils.safeGetString(dbResult, "qblock_name"); this.otherXml = JDBCUtils.safeGetString(dbResult, "other_xml"); Integer parent_id = JDBCUtils.safeGetInteger(dbResult, "parent_id"); if (parent_id != null) { parent = prevNodes.get(parent_id); } if (parent != null) { if (parent.nested == null) { parent.nested = new ArrayList<>(); } parent.nested.add(this); } } @Override public OraclePlanNode getParent() { return parent; } @Override public Collection<OraclePlanNode> getNested() { return nested; } //@Property(name = "ID", order = 0, viewable = true, description = "Node ID") public int getId() { return id; } @Property(order = 1, viewable = true) public String getOperation() { if (CommonUtils.isEmpty(options)) { return operation; } else { return operation + " (" + options + ")"; } } //@Property(name = "Options", order = 2, viewable = true, description = "A variation on the operation described in the Operation column") public String getOptions() { return options; } //@Property(name = "Type", order = 3, viewable = true, description = "Object type") public String getObjectType() { return objectType; } //@Property(name = "Owner", order = 4, viewable = true, description = "Object owner (schema)") // public Object getObjectOwner() // { // final OracleSchema schema = dataSource.schemaCache.getCachedObject(objectOwner); // return schema == null ? objectOwner : schema; // } @Property(order = 5, viewable = true, supportsPreview = true) public Object getObject(DBRProgressMonitor monitor) throws DBException { if (monitor == null || CommonUtils.isEmpty(objectOwner)) { return objectName == null ? "" : objectName; } String objectTypeName = objectType; final int divPos = objectTypeName == null ? -1 : objectTypeName.indexOf('('); if (divPos != -1) { objectTypeName = objectTypeName.substring(0, divPos).trim(); } if (OracleObjectType.INDEX.name().equals(objectTypeName)) { // Get index from parent table - reading of all indexes takes too much time for (OraclePlanNode parentNode = parent; parentNode != null; parentNode = parentNode.getParent()) { final Object parentObject = parentNode.getObject(monitor); if (parentObject instanceof OracleTablePhysical) { return ((OracleTablePhysical) parentObject).getIndex(monitor, objectName); } } return objectName; } else { objectTypeName = OracleObjectType.TABLE.name(); } return OracleObjectType.resolveObject( monitor, dataSource, objectNode, objectTypeName, objectOwner, objectName); } //@Property(name = "Alias", order = 6, viewable = true, description = "Object alias") public String getAlias() { return objectAlias; } @Property(order = 7, viewable = true) public String getOptimizer() { return optimizer; } @Property(order = 8, viewable = true) public long getCost() { return cost; } @Property(order = 9, viewable = true) public long getCardinality() { return cardinality; } @Property(order = 10, viewable = true) public long getBytes() { return bytes; } @Override public String toString() { return operation + " " + CommonUtils.toString(options) + " " + CommonUtils.toString(objectName); } }