package com.tesora.dve.sql.schema;
/*
* #%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.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.tesora.dve.common.catalog.DistributionModel;
import com.tesora.dve.common.catalog.UserTable;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.sql.schema.cache.SchemaEdge;
import com.tesora.dve.sql.util.ListSet;
public class ContainerDistributionVector extends DistributionVector {
private SchemaEdge<PEContainer> container;
@SuppressWarnings("unchecked")
public ContainerDistributionVector(SchemaContext pc, PEContainer container, boolean skipDVCheck) {
super(pc,Collections.EMPTY_LIST,DistributionVector.Model.CONTAINER,skipDVCheck);
this.container = StructuralUtils.buildEdge(pc,container, false);
}
@SuppressWarnings("unchecked")
public ContainerDistributionVector(SchemaContext pc, PEAbstractTable<?> t, UserTable ut) {
super(pc,t,ut,Model.CONTAINER);
this.container = StructuralUtils.buildEdge(pc,PEContainer.load(ut.getContainer(),pc),true);
}
@SuppressWarnings("unchecked")
private ContainerDistributionVector(SchemaContext pc, SchemaEdge<PEContainer> cont) {
super(pc,Collections.EMPTY_LIST,DistributionVector.Model.CONTAINER,true);
this.container = cont;
}
@Override
public PEContainer getContainer(SchemaContext pc) {
return this.container.get(pc);
}
@Override
public RangeDistribution getDistributedWhollyOnTenantColumn(SchemaContext sc) {
// a container is distributed wholly on the tenant column if the backing container is range distributed
return getRange(sc);
}
protected RangeDistribution getRange(SchemaContext sc) {
return getContainer(sc).getRange(sc);
}
@Override
protected void persistForTable(PEAbstractTable<?> pet, UserTable targ, SchemaContext sc) throws PEException {
PEContainer cont = getContainer(sc);
targ.setContainer(cont.persistTree(sc));
if (cont.getContainerDistributionModel() == DistributionVector.Model.RANGE) {
VectorRange vr = new VectorRange(sc, cont.getRange(sc));
vr.setTable(sc, pet);
vr.persistTree(sc);
}
}
public Model getContainerDistributionModel(SchemaContext sc) {
return getContainer(sc).getContainerDistributionModel();
}
@Override
public boolean usesColumns(SchemaContext sc) {
return getContainerDistributionModel(sc).getUsesColumns();
}
@Override
public ListSet<PEColumn> getColumns(SchemaContext sc) {
return getColumns(sc,false);
}
public ListSet<PEColumn> getColumns(SchemaContext sc, boolean init) {
if (getContainerDistributionModel(sc).getUsesColumns()) {
ListSet<PEColumn> out = new ListSet<PEColumn>();
// tenant column may not have been injected yet
PEColumn tenantColumn = getTable().getTenantColumn(sc,init);
if (tenantColumn != null)
out.add(tenantColumn);
return out;
}
return super.getColumns(sc);
}
@Override
protected boolean comparableJoinForDistribution(SchemaContext pc, DistributionVector other, Map<PEColumn, PEColumn> joinedColumns, boolean schemaOnly) {
// different containers - never comparable
ContainerDistributionVector ocdv = (ContainerDistributionVector) other;
if (!ocdv.getContainer(pc).equals(getContainer(pc)))
return false;
if (schemaOnly || pc.getPolicyContext().getCurrentTenant() != null) {
// schema only test (during create table no tenant is needed) or
// the container is set to a particular tenant or the global tenant.
return true;
} else {
// no container context set, fallback to the default
return super.comparableJoinForDistribution(pc,other,joinedColumns, schemaOnly);
}
}
@Override
public boolean hasJoinRequiredColumns(SchemaContext pc, ListSet<PEColumn> joinCols) {
// if this is a container context - the join works regardless of the columns
if (pc.getPolicyContext().getCurrentTenant() != null)
return true;
else
return super.hasJoinRequiredColumns(pc, joinCols);
}
@Override
public DistributionVector adapt(final SchemaContext sc, final PEAbstractTable<?> ontoTable) {
ContainerDistributionVector cdv = new ContainerDistributionVector(sc,container);
cdv.setTable(sc, ontoTable);
return cdv;
}
@Override
public boolean collectDifferences(SchemaContext sc, List<String> messages,
Persistable<DistributionVector, DistributionModel> oth, boolean first,
@SuppressWarnings("rawtypes") Set<Persistable> visited) {
if (visited.contains(this) && visited.contains(oth)) {
return false;
}
visited.add(this);
visited.add(oth);
if (super.collectDifferences(sc, messages, oth, first, visited))
return true;
ContainerDistributionVector other = (ContainerDistributionVector) oth.get();
if (maybeBuildDiffMessage(sc,messages, "container", getContainer(sc), other.getContainer(sc), first, visited))
return true;
return false;
}
@Override
public Integer getRangeID(SchemaContext pc) {
RangeDistribution rd = getRange(pc);
if (rd == null) return null;
return rd.getPersistentID();
}
}