package com.tesora.dve.sql.statement.ddl;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.resultset.ColumnSet;
import com.tesora.dve.resultset.IntermediateResultSet;
import com.tesora.dve.resultset.ResultRow;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.parser.ExtractedLiteral;
import com.tesora.dve.sql.schema.ExplainOptions;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.schema.cache.PlanCacheKey;
import com.tesora.dve.sql.schema.cache.RegularCachedPlan;
import com.tesora.dve.sql.schema.cache.SchemaCache;
import com.tesora.dve.sql.schema.cache.SchemaSourceFactory;
import com.tesora.dve.sql.transform.behaviors.BehaviorConfiguration;
import com.tesora.dve.sql.transform.execution.DDLQueryExecutionStep;
import com.tesora.dve.sql.transform.execution.RebuiltPlan;
import com.tesora.dve.sql.transform.execution.RootExecutionPlan;
import com.tesora.dve.sql.transform.execution.ExecutionSequence;
import com.tesora.dve.sql.transform.execution.StepExecutionStatistics;
import com.tesora.dve.sql.util.UnaryProcedure;
public class ShowPlanCacheStatement extends SchemaQueryStatement {
private boolean stats;
public ShowPlanCacheStatement(boolean showStats) {
super(true, "PLAN CACHE", null);
this.stats = showStats;
}
@Override
public void plan(SchemaContext pc, ExecutionSequence es, BehaviorConfiguration config) throws PEException {
SchemaCache global = SchemaSourceFactory.peekGlobalCache();
ArrayList<ResultRow> rows = new ArrayList<ResultRow>();
Accumulator acc = new Accumulator(pc,stats, rows);
global.applyOnPlans(acc);
ColumnSet cs = new ColumnSet();
cs.addColumn("Database",255,"varchar",Types.VARCHAR);
cs.addColumn("Query",255,"varchar",Types.VARCHAR);
RootExecutionPlan.addExplainColumnHeaders(cs);
if (stats)
StepExecutionStatistics.addColumnHeaders(cs);
es.append(new DDLQueryExecutionStep("PLAN CACHE",new IntermediateResultSet(cs,rows)));
}
private static class Accumulator extends UnaryProcedure<RegularCachedPlan> {
private final boolean statsToo;
private final List<ResultRow> rows;
private final ExplainOptions opts;
private final SchemaContext cntxt;
public Accumulator(SchemaContext sc, boolean doStats, List<ResultRow> acc) {
this.statsToo = doStats;
this.rows = acc;
if (statsToo)
this.opts = ExplainOptions.NONE.setPlanCache().setStatistics();
else
this.opts = ExplainOptions.NONE.setPlanCache();
cntxt = sc;
}
@Override
public void execute(RegularCachedPlan object) {
List<ExtractedLiteral.Type> types = object.getLiteralTypes();
if (types == null) return;
PlanCacheKey pck = object.getKey();
String dbName = pck.getDatabase().getName().getUnqualified().getUnquotedName().get();
SchemaContext sc = SchemaContext.makeImmutableIndependentContext(cntxt);
ArrayList<ExtractedLiteral> fakes = new ArrayList<ExtractedLiteral>();
for(int i = 0; i < types.size(); i++) {
ExtractedLiteral.Type t = types.get(i);
if (t == ExtractedLiteral.Type.STRING) {
fakes.add(ExtractedLiteral.makeStringLiteral("'" + Integer.toString(i) + "'", -1));
} else if (t == ExtractedLiteral.Type.DECIMAL) {
fakes.add(ExtractedLiteral.makeDecimalLiteral(Double.toString(i * 1.0), -1));
} else if (t == ExtractedLiteral.Type.INTEGRAL) {
fakes.add(ExtractedLiteral.makeStringLiteral(Integer.toString(i), -1));
} else if (t == ExtractedLiteral.Type.HEX) {
fakes.add(ExtractedLiteral.makeHexLiteral(Integer.toString(i), -1));
} else {
throw new SchemaException(Pass.PLANNER, "Unknown extracted literal type: " + t);
}
}
RebuiltPlan rp = null;
try {
rp = object.showPlan(sc, fakes);
} catch (PEException pe) {
throw new SchemaException(Pass.PLANNER, "Unable to build show plan", pe);
}
ArrayList<ResultRow> planRows = new ArrayList<ResultRow>();
rp.getEp().explain(sc, rp.getBoundValues(), rp.getEp(), planRows, opts);
for(ResultRow rr : planRows) {
ResultRow nr = new ResultRow();
nr.addResultColumn(dbName);
nr.addResultColumn(pck.getShrunk());
nr.getRow().addAll(rr.getRow());
rows.add(nr);
}
}
}
}