package com.tesora.dve.sql.transform.execution;
/*
* #%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.util.ArrayList;
import java.util.List;
import com.tesora.dve.db.Emitter.EmitOptions;
import com.tesora.dve.distribution.IKeyValue;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.queryplan.QueryStepMultiInsertByKeyOperation;
import com.tesora.dve.queryplan.QueryStepMultiInsertByKeyOperation.StatementSource;
import com.tesora.dve.queryplan.QueryStepOperation;
import com.tesora.dve.resultset.ProjectionInfo;
import com.tesora.dve.server.messaging.SQLCommand;
import com.tesora.dve.sql.parser.ParserOptions;
import com.tesora.dve.sql.schema.ConnectionValues;
import com.tesora.dve.sql.schema.Database;
import com.tesora.dve.sql.schema.JustInTimeInsert;
import com.tesora.dve.sql.schema.PEStorageGroup;
import com.tesora.dve.sql.schema.PETable;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.schema.ValueManager;
import com.tesora.dve.sql.util.Functional;
import com.tesora.dve.sql.util.Pair;
import com.tesora.dve.sql.util.UnaryFunction;
public class LateSortingInsertExecutionStep extends DirectExecutionStep {
// if true we ignore whatever update count we get after sorting
protected boolean ignoreUpdateCount;
private LateSortingInsertExecutionStep(SchemaContext pc, Database<?> db, PEStorageGroup tsg, PETable tab, boolean ignoreUpdateCount) throws PEException {
super(db, tsg, ExecutionType.INSERT, tab.getDistributionVector(pc), null, null, null);
this.ignoreUpdateCount = ignoreUpdateCount;
}
public static LateSortingInsertExecutionStep build(SchemaContext pc, Database<?> db, PEStorageGroup tsg, PETable tab,
boolean ignoreUpdateCount) throws PEException {
return new LateSortingInsertExecutionStep(pc, db, tsg, tab, ignoreUpdateCount);
}
@Override
public Long getlastInsertId(ValueManager vm, SchemaContext sc, ConnectionValues cv) {
return cv.getLastInsertId();
}
@Override
public Long getUpdateCount(SchemaContext sc, ConnectionValues cv) {
if (ignoreUpdateCount)
return null;
List<JustInTimeInsert> late = cv.getLateSortedInserts();
long uc = 0;
for(JustInTimeInsert jti : late)
uc += jti.getUpdateCount();
return uc;
}
@Override
public void schedule(ExecutionPlanOptions opts, List<QueryStepOperation> qsteps, ProjectionInfo projection,
SchemaContext sc, ConnectionValuesMap cvm, ExecutionPlan containing)
throws PEException {
ConnectionValues cv = cvm.getValues(containing);
StatementSource src = null;
if (containing.isRoot()) {
List<JustInTimeInsert> late = cv.getLateSortedInserts();
List<Pair<IKeyValue,SQLCommand>> computed = new ArrayList<Pair<IKeyValue,SQLCommand>>();
for(JustInTimeInsert jti : late) {
SQLCommand sqlc = jti.getSQL();
sqlc.withReferenceTime(cv.getCurrentTimestamp());
computed.add(new Pair<IKeyValue,SQLCommand>(jti.getKey().getDetachedKey(sc, cv),sqlc));
}
src = new PlannerTimeInserts(computed);
} else {
src = new RunTimeInserts();
}
QueryStepMultiInsertByKeyOperation qso = new QueryStepMultiInsertByKeyOperation(getStorageGroup(sc,cv),getPersistentDatabase(),src);
qso.setStatistics(getStepStatistics(sc));
qsteps.add(qso);
}
@Override
public void display(SchemaContext sc, ConnectionValuesMap cvm, ExecutionPlan containing, List<String> buf, String indent, EmitOptions opts) {
String execType = getEffectiveExecutionType().name();
StringBuilder prefix = new StringBuilder();
ConnectionValues cv = cvm.getValues(containing);
prefix.append(indent).append(execType).append(" on ").append((getDatabase() == null ? "null" : getDatabase().getName().get()))
.append("/").append(getStorageGroup(sc,cv));
if (!containing.isRoot()) {
buf.add("inserts not available at planning time");
return;
}
for(JustInTimeInsert jti : cv.getLateSortedInserts()) {
buf.add(prefix.toString());
if (opts == null)
buf.add(indent + " sql: '" + jti.getSQL() + "'");
else {
buf.add(indent + " sql:");
buf.add(jti.getSQL().getRawSQL());
}
buf.add(indent + " dist key: " + jti.getKey().describe(cv));
}
}
private static class RunTimeInserts implements StatementSource {
@Override
public List<Pair<IKeyValue, SQLCommand>> generate(final SchemaContext sc,
final ConnectionValues cv) {
ParserOptions was = sc.getOptions();
try {
sc.setOptions(was.setNestedPlan());
return Functional.apply(cv.getLateSortedInserts(), new UnaryFunction<Pair<IKeyValue,SQLCommand>,JustInTimeInsert>() {
@Override
public Pair<IKeyValue, SQLCommand> evaluate(
JustInTimeInsert object) {
SQLCommand sqlc = object.getSQL();
sqlc.withReferenceTime(cv.getCurrentTimestamp());
return new Pair<IKeyValue,SQLCommand>(object.getKey().getDetachedKey(sc, cv),sqlc);
}
});
} finally {
sc.setOptions(was);
}
}
}
private static class PlannerTimeInserts implements StatementSource {
private final List<Pair<IKeyValue,SQLCommand>> stmts;
public PlannerTimeInserts(List<Pair<IKeyValue,SQLCommand>> stmts) {
this.stmts = stmts;
}
@Override
public List<Pair<IKeyValue, SQLCommand>> generate(SchemaContext sc,
ConnectionValues cv) {
return stmts;
}
}
}