/*
* DBeaver - Universal Database Manager
* Copyright (C) 2013-2015 Denis Forveille (titou10.titou10@gmail.com)
* 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.db2.model.plan;
import org.jkiss.dbeaver.ext.db2.DB2Constants;
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.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.utils.CommonUtils;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* DB2 EXPLAIN_OPERATOR table
*
* @author Denis Forveille
*/
public class DB2PlanOperator extends DB2PlanNode {
private static final String SEL_BASE_SELECT;
static {
StringBuilder sb = new StringBuilder(1024);
sb.append("SELECT *");
sb.append(" FROM %s.%s");
sb.append(" WHERE EXPLAIN_REQUESTER = ?"); // 1
sb.append(" AND EXPLAIN_TIME = ?"); // 2
sb.append(" AND SOURCE_NAME = ?");// 3
sb.append(" AND SOURCE_SCHEMA = ?");// 4
sb.append(" AND SOURCE_VERSION = ?");// 5
sb.append(" AND EXPLAIN_LEVEL = ?");// 6
sb.append(" AND STMTNO = ?");// 7
sb.append(" AND SECTNO = ?");// 8
sb.append(" AND OPERATOR_ID = ?");// 9
sb.append(" ORDER BY %s");// 9
sb.append(" WITH UR");
SEL_BASE_SELECT = sb.toString();
}
private DB2PlanStatement db2Statement;
private String planTableSchema;
private List<DB2PlanOperatorArgument> listArguments;
private List<DB2PlanOperatorPredicate> listPredicates;
private String displayName;
private String nodename;
private Integer operatorId;
private DB2PlanOperatorType operatorType;
private Double totalCost;
private Double estimatedCardinality = -1d;
// ------------
// Constructors
// ------------
public DB2PlanOperator(JDBCSession session, JDBCResultSet dbResult, DB2PlanStatement db2Statement, String planTableSchema)
throws SQLException
{
this.db2Statement = db2Statement;
this.planTableSchema = planTableSchema;
this.operatorId = JDBCUtils.safeGetInteger(dbResult, "OPERATOR_ID");
this.operatorType = CommonUtils.valueOf(DB2PlanOperatorType.class, JDBCUtils.safeGetString(dbResult, "OPERATOR_TYPE"));
this.totalCost = JDBCUtils.safeGetDouble(dbResult, "TOTAL_COST");
this.nodename = buildName(operatorId);
this.displayName = nodename + " - " + operatorType;
loadChildren(session);
}
@Override
public void setEstimatedCardinality(Double estimatedCardinality)
{
// DF: not sure if this rule is correct. Seems to be OK
this.estimatedCardinality = Math.max(this.estimatedCardinality, estimatedCardinality);
}
@Override
public String toString()
{
return displayName;
}
@Override
public String getNodeName()
{
return nodename;
}
// --------
// Helpers
// --------
public static String buildName(Integer operatorId)
{
return String.valueOf(operatorId);
}
// ----------------
// Pproperties
// ----------------
@Property(viewable = true, order = 1)
public DB2PlanOperatorType getOperatorType()
{
return operatorType;
}
@Property(viewable = true, order = 2)
public Integer getOperatorId()
{
return operatorId;
}
@Property(viewable = true, order = 3)
public String getDisplayName()
{
return ""; // Looks better without a name...
}
@Property(viewable = true, order = 4, format = DB2Constants.PLAN_COST_FORMAT)
public Double getTotalCost()
{
return totalCost;
}
@Property(viewable = true, order = 5, format = DB2Constants.PLAN_COST_FORMAT)
public Double getEstimatedCardinality()
{
return estimatedCardinality;
}
@Property(viewable = false, order = 6)
public List<DB2PlanOperatorArgument> getArguments()
{
return listArguments;
}
@Property(viewable = false, order = 7)
public List<DB2PlanOperatorPredicate> getPredicates()
{
return listPredicates;
}
// -------------
// Load children
// -------------
private void loadChildren(JDBCSession session) throws SQLException
{
listArguments = new ArrayList<>();
try (JDBCPreparedStatement sqlStmt = session.prepareStatement(
String.format(SEL_BASE_SELECT, planTableSchema, "EXPLAIN_ARGUMENT", "ARGUMENT_TYPE")))
{
setQueryParameters(sqlStmt);
try (JDBCResultSet res = sqlStmt.executeQuery()) {
while (res.next()) {
listArguments.add(new DB2PlanOperatorArgument(res));
}
}
}
listPredicates = new ArrayList<>();
try (JDBCPreparedStatement sqlStmt = session.prepareStatement(
String.format(SEL_BASE_SELECT, planTableSchema, "EXPLAIN_PREDICATE", "PREDICATE_ID")))
{
setQueryParameters(sqlStmt);
try (JDBCResultSet res = sqlStmt.executeQuery()) {
while (res.next()) {
listPredicates.add(new DB2PlanOperatorPredicate(res, this));
}
}
}
}
private void setQueryParameters(JDBCPreparedStatement sqlStmt) throws SQLException
{
sqlStmt.setString(1, db2Statement.getExplainRequester());
sqlStmt.setTimestamp(2, db2Statement.getExplainTime());
sqlStmt.setString(3, db2Statement.getSourceName());
sqlStmt.setString(4, db2Statement.getSourceSchema());
sqlStmt.setString(5, db2Statement.getSourceVersion());
sqlStmt.setString(6, db2Statement.getExplainLevel());
sqlStmt.setInt(7, db2Statement.getStmtNo());
sqlStmt.setInt(8, db2Statement.getSectNo());
sqlStmt.setInt(9, operatorId);
}
}