package com.tesora.dve.sql.statement.session;
/*
* #%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.HashMap;
import java.util.List;
import com.tesora.dve.db.DBResultConsumer;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.queryplan.ExecutionState;
import com.tesora.dve.queryplan.QueryStepGeneralOperation.AdhocOperation;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.node.expression.LiteralExpression;
import com.tesora.dve.sql.schema.Name;
import com.tesora.dve.sql.schema.PEColumn;
import com.tesora.dve.sql.schema.PEContainer;
import com.tesora.dve.sql.schema.PEContainerTenant;
import com.tesora.dve.sql.schema.PETable;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.transform.behaviors.BehaviorConfiguration;
import com.tesora.dve.sql.transform.execution.ExecutionSequence;
import com.tesora.dve.sql.transform.execution.TransientSessionExecutionStep;
import com.tesora.dve.sql.util.Pair;
import com.tesora.dve.worker.WorkerGroup;
public class UseContainerStatement extends SessionStatement {
private List<Pair<PEColumn,LiteralExpression>> values;
private PEContainerTenant tenant;
private PEContainer container;
// ctor for global
public UseContainerStatement(SchemaContext sc, boolean nullContainer) {
this(sc, null, null,null,null, nullContainer);
}
public UseContainerStatement(SchemaContext sc, PEContainer container, PETable baseTable, List<PEColumn> discCols, List<Pair<LiteralExpression,Name>> keyvals, boolean nullContainer) {
super();
if (keyvals == null) {
values = null;
if (nullContainer)
tenant = null;
else
tenant = new PEContainerTenant(sc,null,null);
} else {
this.container = container;
values = normalizeKey(sc, baseTable,discCols,keyvals);
String lookup = PEContainerTenant.buildDiscriminantValue(sc, sc.getValues(), values);
tenant = sc.findContainerTenant(container,lookup);
if (tenant == null)
throw new SchemaException(Pass.SECOND, "No such container for discriminant " + lookup);
}
}
private List<Pair<PEColumn,LiteralExpression>> normalizeKey(SchemaContext pc, PETable bt, List<PEColumn> discCols, List<Pair<LiteralExpression,Name>> in) {
HashMap<PEColumn,LiteralExpression> vals = new HashMap<PEColumn,LiteralExpression>();
for(int i = 0; i < in.size(); i++) {
Pair<LiteralExpression,Name> p = in.get(i);
PEColumn dc = null;
if (p.getSecond() != null) {
dc = bt.lookup(pc, p.getSecond());
if (dc == null)
throw new SchemaException(Pass.SECOND, "No such column in table " + bt.getName(pc,pc.getValues()).getSQL());
} else {
dc = discCols.get(i);
}
LiteralExpression already = vals.get(dc);
if (already != null)
throw new SchemaException(Pass.SECOND, "Duplicate discriminant column value: " + dc.getName().getSQL());
vals.put(dc,p.getFirst());
}
List<Pair<PEColumn,LiteralExpression>> out = new ArrayList<Pair<PEColumn,LiteralExpression>>();
for(PEColumn pec : discCols) {
out.add(new Pair<PEColumn,LiteralExpression>(pec,vals.get(pec)));
}
return out;
}
public boolean isGlobal() {
return tenant != null && tenant.isGlobalTenant();
}
public boolean isNull() {
return tenant == null;
}
public PEContainer getContainer() {
return container;
}
public List<Pair<PEColumn,LiteralExpression>> getDiscriminant() {
return values;
}
public PEContainerTenant getTenant() {
return tenant;
}
@Override
public void plan(SchemaContext pc, ExecutionSequence es, BehaviorConfiguration config) throws PEException {
es.append(new TransientSessionExecutionStep(getSQL(pc),new AdhocOperation() {
@Override
public void execute(ExecutionState estate, WorkerGroup wg, DBResultConsumer resultConsumer) throws Throwable {
estate.getConnection().setCurrentTenant(tenant);
}
}));
}
}