package com.tesora.dve.sql.transexec;
/*
* #%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.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.tesora.dve.common.MultiMap;
import com.tesora.dve.common.PEConstants;
import com.tesora.dve.common.catalog.AutoIncrementTracker;
import com.tesora.dve.common.catalog.CatalogDAO;
import com.tesora.dve.common.catalog.CatalogEntity;
import com.tesora.dve.common.catalog.Container;
import com.tesora.dve.common.catalog.ContainerTenant;
import com.tesora.dve.common.catalog.DistributionModel;
import com.tesora.dve.common.catalog.DynamicPolicy;
import com.tesora.dve.common.catalog.ExternalService;
import com.tesora.dve.common.catalog.Key;
import com.tesora.dve.common.catalog.KeyColumn;
import com.tesora.dve.common.catalog.PersistentGroup;
import com.tesora.dve.common.catalog.PersistentSite;
import com.tesora.dve.common.catalog.PersistentTemplate;
import com.tesora.dve.common.catalog.Priviledge;
import com.tesora.dve.common.catalog.Project;
import com.tesora.dve.common.catalog.Provider;
import com.tesora.dve.common.catalog.RawPlan;
import com.tesora.dve.common.catalog.SiteInstance;
import com.tesora.dve.common.catalog.StorageGroup.GroupScale;
import com.tesora.dve.common.catalog.TableVisibility;
import com.tesora.dve.common.catalog.TemporaryTable;
import com.tesora.dve.common.catalog.Tenant;
import com.tesora.dve.common.catalog.User;
import com.tesora.dve.common.catalog.UserColumn;
import com.tesora.dve.common.catalog.UserDatabase;
import com.tesora.dve.common.catalog.UserTable;
import com.tesora.dve.common.catalog.UserTrigger;
import com.tesora.dve.common.catalog.UserView;
import com.tesora.dve.db.DBNative;
import com.tesora.dve.db.NativeTypeCatalog;
import com.tesora.dve.distribution.BroadcastDistributionModel;
import com.tesora.dve.distribution.DistributionRange;
import com.tesora.dve.distribution.IKeyValue;
import com.tesora.dve.distribution.RandomDistributionModel;
import com.tesora.dve.distribution.RangeDistributionModel;
import com.tesora.dve.distribution.RangeTableRelationship;
import com.tesora.dve.distribution.StaticDistributionModel;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.infomessage.ConnectionMessageManager;
import com.tesora.dve.lockmanager.LockSpecification;
import com.tesora.dve.lockmanager.LockType;
import com.tesora.dve.singleton.Singletons;
import com.tesora.dve.siteprovider.onpremise.OnPremiseSiteProvider;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.expression.TableKey;
import com.tesora.dve.sql.parser.InvokeParser;
import com.tesora.dve.sql.parser.ParserOptions;
import com.tesora.dve.sql.schema.*;
import com.tesora.dve.sql.schema.DistributionVector.Model;
import com.tesora.dve.sql.schema.SchemaContext.DistKeyOpType;
import com.tesora.dve.sql.schema.SchemaContext.PersistContext;
import com.tesora.dve.sql.schema.cache.EntityCacheKey;
import com.tesora.dve.sql.schema.cache.PersistentCacheKey;
import com.tesora.dve.sql.schema.cache.SchemaCacheKey;
import com.tesora.dve.sql.schema.cache.SchemaEdge;
import com.tesora.dve.sql.schema.mt.HollowTableVisibility;
import com.tesora.dve.sql.schema.mt.IPETenant;
import com.tesora.dve.sql.schema.mt.PETenant;
import com.tesora.dve.sql.schema.mt.TableScope;
import com.tesora.dve.sql.statement.Statement;
import com.tesora.dve.sql.statement.ddl.DDLStatement;
import com.tesora.dve.sql.statement.ddl.PECreateDatabaseStatement;
import com.tesora.dve.sql.statement.ddl.PECreateStatement;
import com.tesora.dve.sql.statement.ddl.PECreateTableStatement;
import com.tesora.dve.sql.statement.ddl.PECreateTenantTableStatement;
import com.tesora.dve.sql.statement.ddl.PECreateViewStatement;
import com.tesora.dve.sql.statement.ddl.PEDropStatement;
import com.tesora.dve.sql.statement.dml.DMLStatement;
import com.tesora.dve.sql.statement.session.SessionSetVariableStatement;
import com.tesora.dve.sql.statement.session.SessionStatement;
import com.tesora.dve.sql.statement.session.SetExpression;
import com.tesora.dve.sql.statement.session.SetVariableExpression;
import com.tesora.dve.sql.statement.session.UseContainerStatement;
import com.tesora.dve.sql.statement.session.UseDatabaseStatement;
import com.tesora.dve.sql.statement.session.UseStatement;
import com.tesora.dve.sql.transexec.spi.TransientEngine;
import com.tesora.dve.sql.transexec.spi.TransientEngineFactory;
import com.tesora.dve.sql.util.Functional;
import com.tesora.dve.sql.util.ListSet;
import com.tesora.dve.sql.util.UnaryFunction;
import com.tesora.dve.sql.util.UnaryPredicate;
import com.tesora.dve.variables.AbstractVariableAccessor;
import com.tesora.dve.variables.GlobalVariableStore;
import com.tesora.dve.variables.KnownVariables;
import com.tesora.dve.variables.LocalVariableStore;
import com.tesora.dve.variables.VariableManager;
import com.tesora.dve.variables.VariableStoreSource;
import com.tesora.dve.variables.VariableValueStore;
import com.tesora.dve.worker.WorkerGroup.MappingSolution;
/*
* Essentially a mock class of the full engine; used in tests, upgrader, analyzer.
*/
public class TransientExecutionEngine implements CatalogContext, ConnectionContext, VariableStoreSource, TransientEngine {
public static final TransientEngineFactory FACTORY = new TransientEngineFactoryImpl();
private SchemaContext tpc;
private List<PersistentSite> sites = new ArrayList<PersistentSite>();
private List<PersistentGroup> groups = new ArrayList<PersistentGroup>();
private List<UserDatabase> dbs = new ArrayList<UserDatabase>();
private List<Project> projects = new ArrayList<Project>();
private List<DistributionRange> rds = new ArrayList<DistributionRange>();
private List<Tenant> tenants = new ArrayList<Tenant>();
private List<PersistentTemplate> templates = new ArrayList<PersistentTemplate>();
private Map<String, DistributionModel> models;
private Map<UserTable, Long> autoincs = new HashMap<UserTable, Long>();
private MultiMap<String, TableVisibility> scopes = new MultiMap<String, TableVisibility>();
private Map<UserTable,RangeTableRelationship> rangesForTables = new HashMap<UserTable,RangeTableRelationship>();
private List<Container> containers = new ArrayList<Container>();
private List<ContainerTenant> containerTenants = new ArrayList<ContainerTenant>();
private List<UserView> views = new ArrayList<UserView>();
private List<User> users = new ArrayList<User>();
// single default policy
private DynamicPolicy defaultPolicy = null;
// associate a schema cache key with a catalog entity
private Map<SchemaCacheKey<?>,CatalogEntity> cats;
private String tempTableKern;
private int tempTableCounter;
private LocalVariableStore sessionVariables;
private GlobalVariableStore globalVariables = new TransientGlobalVariableStore();
private VariableValueStore userVariables = new VariableValueStore("User",false);
private IPETenant currentTenant = null;
private PEUser currentUser = null;
private Database<?> currentDatabase = null;
private final ConnectionMessageManager messages = new ConnectionMessageManager();
protected TransientExecutionEngine(String ttkern) {
this(ttkern, Singletons.require(DBNative.class).getTypeCatalog());
}
protected TransientExecutionEngine(String ttkern, NativeTypeCatalog types) {
try {
VariableManager.getManager().initialiseTransient(globalVariables);
sessionVariables = globalVariables.buildNewLocalStore();
} catch (PEException pe) {
throw new SchemaException(Pass.FIRST, "Unable to initialize global vars for trans exec engine");
}
sessionVariables.setValue(KnownVariables.DYNAMIC_POLICY, OnPremiseSiteProvider.DEFAULT_POLICY_NAME);
tpc = SchemaContext.createContext(this,this,types,Capability.TRANSIENT);
currentUser = new PEUser(tpc);
users.add(new User(currentUser.getUserScope().getUserName(),
currentUser.getPassword(),
currentUser.getUserScope().getScope(),
true));
models = new HashMap<String, DistributionModel>();
models.put(BroadcastDistributionModel.MODEL_NAME, new BroadcastDistributionModel());
models.put(RandomDistributionModel.MODEL_NAME, new RandomDistributionModel());
models.put(StaticDistributionModel.MODEL_NAME, new StaticDistributionModel());
models.put(RangeDistributionModel.MODEL_NAME, new RangeDistributionModel());
cats = new HashMap<SchemaCacheKey<?>,CatalogEntity>();
// create a couple of fake databases for info schema
dbs.add(new UserDatabase("INFORMATION_SCHEMA",null));
dbs.add(new UserDatabase("mysql",null));
tempTableKern = ttkern;
tempTableCounter = 0;
try {
defaultPolicy = CatalogHelper.generatePolicyConfig(5, OnPremiseSiteProvider.DEFAULT_NAME);
} catch (PEException pe) {
throw new SchemaException(Pass.FIRST, "Unable to build transient default policy");
}
}
@Override
public SchemaContext getPersistenceContext() {
return tpc;
}
@Override
public void setContext(SchemaContext cntxt) {
tpc = cntxt;
}
public SchemaContext parse(String[] in) throws Throwable {
return parse(in,false);
}
// parse and apply. all statements execute in the context of the project.
public SchemaContext parse(String[] in, boolean analyzer) throws Throwable {
// we turn on ignore missing user for the analyzer. it has no effect for the tests.
ParserOptions opts = ParserOptions.TEST.setResolve().setIgnoreMissingUser();
for(String sql : in) {
SchemaContext pc = getPersistenceContext();
pc.refresh(true);
try {
List<Statement> stmts = InvokeParser.parse(InvokeParser.buildInputState(sql, tpc), opts, pc).getStatements();
for(Statement s : stmts) {
dispatch(s);
}
} catch (Exception e) {
if (analyzer)
throw new PEException("TEE unable to parse '" + sql + "': " + e.getMessage(),e);
throw e;
}
}
SchemaContext pc = getPersistenceContext();
pc.refresh(true);
return pc;
}
public void dispatch(Statement s) throws Throwable {
if (s instanceof DDLStatement) {
dispatchCreateStatement(s);
} else if (s instanceof SessionStatement) {
dispatchSessionStatement(s);
} else if (s instanceof DMLStatement) {
// just plan these - we're primarily getting at any catalog related side effects
Statement.getExecutionPlan(tpc,s);
}
}
@SuppressWarnings("rawtypes")
public void dispatchCreateStatement(Statement s) throws Throwable {
if (s instanceof PECreateStatement) {
executeCreateStatement((PECreateStatement<?,?>)s);
} else if (s instanceof PEDropStatement) {
executeDropStatement((PEDropStatement)s);
} else {
throw new IllegalArgumentException("Unknown create statement: " + s.getClass().getName());
}
}
public void dispatchSessionStatement(Statement s) throws Throwable {
if (s instanceof UseStatement) {
UseStatement us = (UseStatement)s;
if (us instanceof UseDatabaseStatement) {
UseDatabaseStatement uds = (UseDatabaseStatement) us;
tpc.setDefaultDatabase(uds.getDatabase(tpc));
currentDatabase = uds.getDatabase(tpc);
setCurrentTenant(null);
}
else if (us.getTarget() instanceof PEProject)
tpc.setDefaultProject((PEProject)us.getTarget());
else if (us.getTarget() instanceof PETenant) {
PETenant ten = (PETenant) us.getTarget();
tpc.setDefaultDatabase(ten.getDatabase(tpc));
currentDatabase = ten.getDatabase(tpc);
setCurrentTenant(ten);
} else
throw new IllegalArgumentException("Invalid use target for transient execution engine: " + us.getTarget().getClass().getName());
} else if (s instanceof UseContainerStatement) {
UseContainerStatement ucs = (UseContainerStatement) s;
PEContainerTenant pect = ucs.getTenant();
setCurrentTenant(pect);
} else if (s instanceof SessionSetVariableStatement) {
SessionSetVariableStatement ssvs = (SessionSetVariableStatement) s;
// see what the var is and update our settings
dispatchSetSessionVar(ssvs);
} else {
throw new IllegalArgumentException("Invalid session statement for transient execution engine: " + s.getClass().getName());
}
}
@SuppressWarnings("rawtypes")
public void executeCreateStatement(PECreateStatement pecs) throws Throwable {
if (pecs.getCreated() instanceof PEDatabase) {
PECreateDatabaseStatement pecds = (PECreateDatabaseStatement) pecs;
List<Statement> extras = pecds.getPrereqs(tpc);
if (extras != null) {
for(Statement s : extras) {
dispatch(s);
}
}
}
boolean tenantCreate = pecs instanceof PECreateTenantTableStatement;
boolean tableCreate = pecs instanceof PECreateTableStatement;
boolean viewCreate = pecs instanceof PECreateViewStatement;
Set<PEForeignKey> postPass = null;
if (tableCreate) {
pecs.normalize(tpc);
PECreateTableStatement pect = (PECreateTableStatement) pecs;
postPass = pect.getModifiedKeys();
}
Persistable p = null;
if (viewCreate)
p = ((PECreateViewStatement)pecs).getViewTable();
else
p = pecs.getCreated();
tpc.beginSaveContext();
PersistContext sc = null;
try {
p.persistTree(tpc,true);
sc = tpc.getSaveContext();
} finally {
tpc.endSaveContext();
}
for(Map.Entry<Persistable<?,?>, CatalogEntity> nm : sc.getAssociation().entrySet()) {
Persistable<?,?> t = nm.getKey();
CatalogEntity cat = nm.getValue();
if (cat instanceof UserColumn || cat instanceof DistributionModel || (cat instanceof UserTable && !tenantCreate)
|| cat instanceof Key || cat instanceof KeyColumn || cat instanceof UserTrigger)
continue;
if (tenantCreate && (cat instanceof UserTable)) {
// we dynamically create the table scope via reloading callback - not available via static computation.
// fake that out now.
PECreateTenantTableStatement stmt = (PECreateTenantTableStatement) pecs;
PETenant onTenant = stmt.getTenant();
Name logicalName = (stmt.getLogicalName() == null ? stmt.getCreated().getName() : stmt.getLogicalName());
t = onTenant.setVisible(tpc, (PETable)t, logicalName, null, null);
cat = new TableVisibility(findTenant(PEConstants.LANDLORD_TENANT),(UserTable)cat,
(stmt.getLogicalName() == null ? null : stmt.getLogicalName().getUnquotedName().get()),null);
}
SchemaCacheKey<?> sck = t.getCacheKey();
if (sck == null) throw new PEException("Missing cache key impl for " + t.getClass().getName() + " cat entity " + cat);
cats.put(sck,cat);
if (cat instanceof UserDatabase) {
UserDatabase udb = (UserDatabase) cat;
safeAdd(dbs,udb);
if (udb.getMultitenantMode().isMT()) {
Tenant exists = findTenant(PEConstants.LANDLORD_TENANT);
if (exists == null) {
exists = new Tenant(udb, PEConstants.LANDLORD_TENANT, PEConstants.LANDLORD_TENANT);
setID(exists,42);
safeAdd(tenants,exists);
}
}
}
else if (cat instanceof PersistentGroup)
safeAdd(groups,(PersistentGroup)cat);
else if (cat instanceof Project)
safeAdd(projects,(Project)cat);
else if (cat instanceof PersistentSite)
safeAdd(sites,(PersistentSite)cat);
else if (cat instanceof DistributionRange)
safeAdd(rds,(DistributionRange)cat);
else if (cat instanceof RangeTableRelationship) {
RangeTableRelationship rtr = (RangeTableRelationship) cat;
rangesForTables.put(rtr.getTable(),rtr);
} else if (cat instanceof TableVisibility) {
TableVisibility tv = (TableVisibility) cat;
scopes.put(PEConstants.LANDLORD_TENANT, tv);
} else if (cat instanceof Container) {
safeAdd(containers, (Container)cat);
} else if (cat instanceof PersistentTemplate) {
safeAdd(templates, (PersistentTemplate)cat);
} else if (cat instanceof UserView) {
safeAdd(views, (UserView)cat);
} else if (cat instanceof User) {
safeAdd(users, (User)cat);
}
else
throw new PEException("Unknown item: " + cat);
}
if (postPass != null) {
tpc.beginSaveContext();
try {
for(PEForeignKey pefk : postPass) {
// flush the changes out
pefk.persistTree(tpc,true);
}
} finally {
tpc.endSaveContext();
}
}
}
private <T> void safeAdd(List<T> into, T obj) {
if (!into.contains(obj))
into.add(obj);
}
public void executeDropStatement(PEDropStatement<?, ?> peds) throws Exception {
}
@Override
public Project findProject(String name) {
for(Project p : projects)
if (p.getName().equals(name))
return p;
return null;
}
@Override
public Project createProject(String name) {
return new Project(name);
}
@Override
public PersistentGroup findPersistentGroup(String name) {
for(PersistentGroup pg : groups)
if (pg.getName().equals(name))
return pg;
return null;
}
@Override
public PersistentGroup createPersistentGroup(String name) {
return new PersistentGroup(name);
}
@Override
public PersistentSite createPersistentSite(String name, String haType,
SiteInstance master, SiteInstance[] replicants) throws PEException {
PersistentSite site = new PersistentSite(name, haType);
site.setMasterInstance(master);
site.addAll(replicants);
return site;
}
@Override
public PersistentSite createPersistentSite(String name, String url, String user, String password) throws PEException {
return new PersistentSite(name, new SiteInstance(name, url, user, password));
}
@Override
public PersistentSite findPersistentSite(String name) {
for(PersistentSite ps : sites)
if (ps.getName().equals(name))
return ps;
return null;
}
@Override
public SiteInstance findSiteInstance(String name) {
return null;
}
@Override
public SiteInstance createSiteInstance(String name, String url, String user, String password, boolean master, String status) {
return null;
}
@Override
public void persistToCatalog(Object o) {
}
@Override
public Map<String, DistributionModel> getDistributionModelMap() {
return models;
}
@Override
public UserDatabase findUserDatabase(String n) {
for(UserDatabase ud : dbs)
if (ud.getName().equals(n))
return ud;
return null;
}
@Override
public UserTable findUserTable(Name name, int dbid, String dbName) {
UserDatabase udb = null;
for(UserDatabase u : dbs) {
if (u.getName().equals(dbName)) {
udb = u;
break;
}
}
if (udb == null) return null;
try {
return udb.getTableByName(name.get(), false);
} catch (PEException pe) {
throw new RuntimeException(pe);
}
}
@Override
public TableVisibility findTableVisibility(String tenantName, int tenantID,
String tableName) {
Collection<TableVisibility> tenscopes = scopes.get(tenantName);
if (tenscopes == null) return null;
for(TableVisibility tv : tenscopes) {
if (tv.getTable().getName().equals(tableName) || tableName.equals(tv.getLocalName()))
return tv;
}
return null;
}
@Override
public DistributionRange findDistributionRange(String name, String groupName) {
for(DistributionRange dr : rds)
if (dr.getName().equals(name) && dr.getStorageGroup().getName().equals(groupName))
return dr;
return null;
}
@Override
public List<DistributionRange> findDistributionRange(final String name) {
return Functional.select(rds, new UnaryPredicate<DistributionRange>() {
@Override
public boolean test(DistributionRange object) {
return object.getName().equals(name);
}
});
}
@Override
public RangeTableRelationship findRangeTableRelationship(UserTable forTable) {
return rangesForTables.get(forTable);
}
@Override
public boolean isPersistent() {
// the persistent schema holds less info than the transient schema - we do some extra tests with the
// transient schema in the meantime.
return false;
}
@Override
public void addAutoIncrement(SchemaContext sc, PETable onTable, Long offset) {
autoincs.put(onTable.getPersistent(tpc), (offset == null ? new Long(1): offset));
}
@Override
public long getNextIncrementValue(SchemaContext sc, PETable onTable) {
UserTable ut = onTable.getPersistent(tpc);
Long v = autoincs.get(ut);
Long ret = new Long(v.longValue() + 1);
autoincs.put(ut, ret);
return v.longValue();
}
@Override
public long getNextIncrementValueChunk(SchemaContext sc, PETable onTable, long blockSize) {
UserTable ut = onTable.getPersistent(tpc);
Long v = autoincs.get(ut);
Long mark = new Long(v.longValue() + blockSize);
autoincs.put(ut, mark);
return v.longValue();
}
@Override
public String getTempTableName() {
tempTableCounter++;
return tempTableKern + tempTableCounter;
}
@Override
public MappingSolution mapKey(SchemaContext sc, IKeyValue dk, Model model, DistKeyOpType op, PEStorageGroup onGroup, ConnectionValues cv) throws PEException {
// we don't do anything different by op type, but the persistent version does.
if (Model.RANDOM == model )
return RandomDistributionModel.SINGLETON.mapKeyForQuery(null, onGroup.getPersistent(sc, cv), dk, op);
if (Model.BROADCAST == model)
return BroadcastDistributionModel.SINGLETON.mapKeyForQuery(null, onGroup.getPersistent(sc, cv), dk, op);
if (Model.STATIC == model )
return StaticDistributionModel.SINGLETON.mapKeyForQuery(null, onGroup.getPersistent(sc, cv), dk, op);
if (Model.RANGE == model)
// we use static dist model in place of range for the trans exec engine since range
// does a catalog lookup and there is no catalog
return StaticDistributionModel.SINGLETON.mapKeyForQuery(null, onGroup.getPersistent(sc, cv), dk, op);
throw new PEException("Unknown dist model kind: " + model.getPersistentName());
}
private static final String SINGLE_SITE_GROUP_QUERY =
"SELECT a FROM PersistentSite AS a ORDER BY a.name ASC";
@Override
public List<CatalogEntity> query(String query, Map<String, Object> params) {
if (SINGLE_SITE_GROUP_QUERY.equals(query) && params.isEmpty())
return Functional.apply(sites, new UnaryFunction<CatalogEntity,PersistentSite>() {
@Override
public CatalogEntity evaluate(PersistentSite object) {
return object;
}
});
throw new SchemaException(Pass.SECOND, "No support for catalog query in transient execution engine");
}
@Override
public Project getDefaultProject() {
throw new SchemaException(Pass.SECOND, "TransientExecutionEngine does not use default project");
}
@Override
public Object findByKey(Class<? extends CatalogEntity> c, int id) {
return null;
}
@Override
public UserTable createTempTable(UserDatabase udb, String name,
DistributionModel dist) {
try {
return UserTable.newTempTable(udb, null, name, dist);
} catch (PEException pe) {
throw new RuntimeException(pe);
}
}
@Override
public List<User> findUsers(String name, String accessSpec) {
List<User> out = new ArrayList<User>();
for(User u : users) {
if (u.getName().equals(name) && u.getAccessSpec().equals(accessSpec))
out.add(u);
}
return out;
}
@Override
public List<UserDatabase> findAllUserDatabases() {
return dbs;
}
@Override
public Tenant findTenant(String extID) {
for(Tenant t : tenants)
if (t.getExternalTenantId().equals(extID))
return t;
return null;
}
@Override
public List<PersistentGroup> findAllGroups() {
return groups;
}
@Override
public PersistentGroup findBalancedPersistentGroup(String prefix) {
return groups.get(0);
}
@SuppressWarnings("unchecked")
@Override
public SchemaEdge<IPETenant> getCurrentTenant() {
if (currentTenant == null)
return StructuralUtils.buildEdge(tpc,null,true);
else
return StructuralUtils.buildEdge(tpc,currentTenant, true);
}
@Override
public boolean allowTenantColumnDecls() {
return true;
}
@Override
public void setSchemaContext(SchemaContext sc) {
// ignore, we are our own schema context
}
@Override
public TableVisibility findVisibilityRecord(int tabid, int tenid) {
return null;
}
@Override
public AutoIncrementTracker getBackingTracker(SchemaContext sc, TableKey tk) {
return null;
}
@Override
public AutoIncrementTracker getBackingTracker(SchemaContext sc, PETable tk) {
return null;
}
@Override
public AutoIncrementTracker getBackingTracker(SchemaContext sc, TableScope tk) {
return null;
}
@Override
public Provider findProvider(String name) {
return null;
}
@Override
public List<Provider> findAllProviders() {
return null;
}
@Override
public DynamicPolicy findPolicy(String name) {
if (OnPremiseSiteProvider.DEFAULT_POLICY_NAME.equals(name)) {
return defaultPolicy;
}
return null;
}
@Override
public List<CatalogEntity> nativeQuery(String query,
Map<String, Object> params, Class<?> targetClass) {
return null;
}
@SuppressWarnings("rawtypes")
@Override
public List nativeQuery(String query, Map<String, Object> params) {
return Collections.emptyList();
}
@Override
public String getVariableValue(AbstractVariableAccessor va) throws PEException {
return va.getValue(this);
}
@Override
public List<List<String>> getVariables(VariableScope vs) throws PEException {
throw new PEException("No support for getVariables in TransientExecutionEngine");
}
private void dispatchSetSessionVar(SessionSetVariableStatement stmt) throws Throwable {
for(SetExpression se : stmt.getSetExpressions()) {
if (se.getKind() == SetExpression.Kind.TRANSACTION_ISOLATION)
throw new SchemaException(Pass.PLANNER, "No support for setting txn isolation in trans exec engine");
SetVariableExpression sve = (SetVariableExpression) se;
sve.getVariable().buildAccessor(getPersistenceContext()).setValue(this, sve.getVariableValue(tpc).toString());
}
}
@Override
public List<PersistentSite> findAllSites() {
return sites;
}
@Override
public void setCurrentTenant(IPETenant ten) {
currentTenant = ten;
}
@Override
public List<UserDatabase> findAllMTDatabases() {
ArrayList<UserDatabase> out = new ArrayList<UserDatabase>();
for(UserDatabase udb : dbs)
if (udb.getMultitenantMode().isMT())
out.add(udb);
return out;
}
@SuppressWarnings("unchecked")
@Override
public SchemaEdge<PEUser> getUser() {
return StructuralUtils.buildEdge(tpc,currentUser,false);
}
@SuppressWarnings("unchecked")
@Override
public SchemaEdge<Database<?>> getCurrentDatabase() {
return StructuralUtils.buildEdge(tpc,currentDatabase, true);
}
@Override
public List<String> findTenantTableNames(Tenant t) {
throw new IllegalStateException("No support for findTenantTableNames in transient execution engine");
}
@Override
public long readNextIncrementValue(SchemaContext sc, TableKey tk) {
return -1;
}
@Override
public void removeNextIncrementValue(SchemaContext sc, TableKey tk, long value) {
}
@Override
public void removeNextIncrementValue(SchemaContext sc, PETable tab, long value) {
}
@Override
public void removeNextIncrementValue(SchemaContext sc, TableScope ts, long value) {
}
@Override
public String getName() {
return "TransientExecutionEngine";
}
@Override
public void refresh(CatalogEntity cat,boolean pessimistic) {
// no backing so by default no refresh
}
@Override
public void acquireLock(LockSpecification ls, LockType type) {
}
@Override
public boolean isInTxn() {
return false;
}
@Override
public CatalogDAO getDAO() {
throw new IllegalStateException("No support for catalogDAO in transient execution engine");
}
@Override
public List<TableVisibility> findTenantsOf(UserTable tab) {
throw new IllegalStateException("No support for findTenantsOf in transient execution engine");
}
@Override
public List<UserTable> findMatchingTables(UserDatabase udb,
String logicalName, String definition) {
throw new IllegalStateException("No support for findMatchingTables in transient execution engine");
}
@Override
public ExternalService findExternalService(String name) {
return null;
}
@Override
public ExternalService createExternalService(String name, String plugin,
String connectUser, boolean usesDataStore, String config) {
return null;
}
@Override
public Priviledge findPrivilege(SchemaContext sc, int userid, String name) {
return null;
}
@Override
public boolean findGlobalPrivilege(SchemaContext sc, PEUser user) {
return false;
}
public static class TransientDynamicGroup extends PEDynamicGroup {
private int size;
public TransientDynamicGroup(GroupScale scale, int size) {
super(scale);
this.size = size;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof PEDynamicGroup)) return false;
PEDynamicGroup pedg = (PEDynamicGroup) other;
return getScale() == pedg.getScale();
}
public String getProviderName() {
return "NoProvider";
}
public String getClassName() {
return "NoClass";
}
@Override
public String toString() {
return "TransientDynamicGroup(" + getProviderName() + "/" + getClassName() + "/" + getScale() + "/" + getCount() +")";
}
public int getCount() {
return size;
}
public String getCodeName() {
String suffix = null;
if (getScale() == GroupScale.AGGREGATE)
suffix = "AGGREGATION";
else
suffix = getScale().toString();
return "TransientExecutionEngine." + suffix;
}
}
public static final TransientDynamicGroup LARGE = new TransientDynamicGroup(GroupScale.LARGE,8);
public static final TransientDynamicGroup MEDIUM = new TransientDynamicGroup(GroupScale.MEDIUM,4);
public static final TransientDynamicGroup SMALL = new TransientDynamicGroup(GroupScale.SMALL,2);
public static final TransientDynamicGroup AGGREGATION = new TransientDynamicGroup(GroupScale.AGGREGATE,1);
// all of the transform tests for now use the same object for the policy
public static final DynamicPolicy transformTestPolicy = new DynamicPolicy(
"TransformTestPolicy", true,
AGGREGATION.getProviderName(), AGGREGATION.getClassName(), AGGREGATION.getCount(),
SMALL.getProviderName(), SMALL.getClassName(), SMALL.getCount(),
MEDIUM.getProviderName(), MEDIUM.getClassName(), MEDIUM.getCount(),
LARGE.getProviderName(), LARGE.getClassName(), LARGE.getCount());
@Override
public <T extends CatalogEntity> T findByKey(PersistentCacheKey pck) {
return null;
}
@Override
public EntityCacheKey buildCacheKey(CatalogEntity ce) {
return new TransientCacheKey(ce);
}
private static class TransientCacheKey implements EntityCacheKey {
private final Class<?> entityClass;
private final int givenHashcode;
public TransientCacheKey(CatalogEntity cat) {
entityClass = cat.getClass();
givenHashcode = cat.hashCode();
}
@Override
public String toString() {
return "TransientCacheKey{" + entityClass.getSimpleName() + "@" + givenHashcode + "}";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((entityClass == null) ? 0 : entityClass.hashCode());
result = prime * result + givenHashcode;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TransientCacheKey other = (TransientCacheKey) obj;
if (entityClass == null) {
if (other.entityClass != null)
return false;
} else if (!entityClass.equals(other.entityClass))
return false;
if (givenHashcode != other.givenHashcode)
return false;
return true;
}
}
public static void setID(Object o, int val) {
Class<?> c = o.getClass();
try {
Field f = c.getDeclaredField("id");
f.setAccessible(true);
f.set(o, val);
} catch (Throwable t) {
throw new RuntimeException("unable to force id on class " + c.getSimpleName(),t);
}
}
@Override
public long getNextIncrementValueChunk(SchemaContext sc, TableScope ts,
long blockSize) {
return 0;
}
@Override
public Container findContainer(String name) {
for(Container container : containers)
if (container.getName().equals(name))
return container;
return null;
}
@Override
public List<UserTable> findContainerMembers(String containerName)
throws PEException {
return null;
}
@Override
public ContainerTenant findContainerTenant(String containerName,
String discriminant) {
for(ContainerTenant ct : containerTenants) {
if (containerName == null && discriminant == null) {
if (ct.isGlobalTenant())
return ct;
} else if (ct.isGlobalTenant()) {
continue;
} else if (ct.getContainer().getName().equals(containerName) && ct.getDiscriminant().equals(discriminant))
return ct;
}
return null;
}
@Override
public ConnectionContext copy() {
return this;
}
@Override
public CatalogContext copy(ConnectionContext cc) {
return this;
}
@Override
public void saveContainerTenant(Container cont, String disc) {
ContainerTenant ct = new ContainerTenant(cont,disc);
setID(ct,containerTenants.size() + 1);
containerTenants.add(ct);
}
@Override
public List<UserTable> findTablesWithUnresolvedFKsTargeting(
String schemaName, String tableName) {
UserDatabase udb = findUserDatabase(schemaName);
if (udb == null)
throw new SchemaException(Pass.PLANNER, "No such database: " + schemaName);
ListSet<UserTable> matching = new ListSet<UserTable>();
for(UserTable ut : udb.getUserTables()) {
for(Key k : ut.getKeys()) {
if (!k.isForeignKey()) continue;
if (k.getReferencedTable() == null && k.getReferencedTableName().equals(tableName)) {
matching.add(ut);
break;
}
}
}
return matching;
}
@Override
public List<UserTable> findTablesWithFKSReferencing(int tabID) {
return null;
}
@Override
public void startTxn() {
}
@Override
public void commitTxn() {
}
@Override
public void rollbackTxn() {
}
@Override
public HollowTableVisibility findHollowTableVisibility(String tenantName, int tenantID, String tableName) {
throw new IllegalStateException("no hollow support in trans. exec. engine");
}
@Override
public boolean hasFilter() {
return false;
}
@Override
public boolean isFilteredTable(Name table) {
return false;
}
@Override
public boolean originatedFromReplicationSlave() {
return false;
}
@Override
public String getCacheName() {
return null;
}
@Override
public int getConnectionId() {
return 67;
}
@Override
public Key findForeignKey(UserDatabase db, Integer tenantID, String name, String constraintName) throws PEException {
return null;
}
@Override
public ConnectionMessageManager getMessageManager() {
return messages;
}
@Override
public long getLastInsertedId() {
return -1;
}
@Override
public PersistentTemplate findTemplate(String name) {
for(PersistentTemplate pt : templates)
if (pt.getName().equals(name))
return pt;
return null;
}
@Override
public List<PersistentTemplate> findMatchTemplates() {
TreeMap<String, PersistentTemplate> byName = new TreeMap<String,PersistentTemplate>();
for(PersistentTemplate pt : templates)
if (pt.getMatch() != null)
byName.put(pt.getName(), pt);
return Functional.toList(byName.values());
}
@Override
public RawPlan findRawPlan(String name) {
return null;
}
@Override
public List<RawPlan> findAllEnabledRawPlans() {
return Collections.emptyList();
}
@Override
public List<TableVisibility> findScopesWithUnresolvedFKsTargeting(
String schemaName, String tableName, int tenantID) {
return null;
}
@Override
public List<TableVisibility> findScopesWithFKsReferencing(int tableID,
int tenantID) {
return null;
}
@Override
public List<TableVisibility> findScopesForFKTargets(int tableID,
int tenantID) {
return null;
}
@Override
public UserView findView(String name, String dbn) {
for(UserView uv : views) {
if (uv.getTable().getName().equals(name) && uv.getTable().getDatabase().getName().equals(dbn))
return uv;
}
return null;
}
@Override
public void setCurrentDatabase(Database<?> db) {
this.currentDatabase = db;
}
@Override
public List<UserTable> findTablesOnGroup(String groupName) {
return null;
}
@Override
public List<User> findAllUsers() {
return null;
}
@Override
public boolean isInXATxn() {
return false;
}
@Override
public List<TemporaryTable> findUserlandTemporaryTable(Integer connID,
String dbName, String tabName) {
// TODO Auto-generated method stub
return null;
}
@Override
public LocalVariableStore getSessionVariableStore() {
return sessionVariables;
}
@Override
public GlobalVariableStore getGlobalVariableStore() {
return globalVariables;
}
@Override
public VariableStoreSource getVariableSource() {
return this;
}
@Override
public VariableValueStore getUserVariableStore() {
return userVariables;
}
@Override
public UserTrigger findTrigger(String name, String dbName) {
// TODO Auto-generated method stub
return null;
}
private static class TransientEngineFactoryImpl implements TransientEngineFactory {
@Override
public TransientEngine create(String ttkern) {
return new TransientExecutionEngine(ttkern);
}
@Override
public TransientEngine create(String ttkern, NativeTypeCatalog types) {
return new TransientExecutionEngine(ttkern, types);
}
}
}