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.util.ArrayList; import java.util.Collections; import java.util.List; import com.tesora.dve.common.catalog.CatalogDAO; import com.tesora.dve.common.catalog.CatalogEntity; import com.tesora.dve.common.catalog.TableVisibility; import com.tesora.dve.common.catalog.Tenant; import com.tesora.dve.common.catalog.UserTable; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.queryplan.QueryStepDDLGeneralOperation.DDLCallback; import com.tesora.dve.server.global.HostService; import com.tesora.dve.server.connectionmanager.SSConnection; import com.tesora.dve.server.messaging.SQLCommand; import com.tesora.dve.singleton.Singletons; import com.tesora.dve.sql.schema.Persistable; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.cache.CacheInvalidationRecord; import com.tesora.dve.sql.schema.cache.InvalidationScope; import com.tesora.dve.sql.schema.mt.AdaptiveMultitenantSchemaPolicyContext; import com.tesora.dve.sql.schema.mt.PETenant; import com.tesora.dve.sql.schema.mt.TableScope; import com.tesora.dve.sql.statement.StatementType; import com.tesora.dve.sql.statement.dml.DeleteStatement; import com.tesora.dve.sql.transform.behaviors.BehaviorConfiguration; import com.tesora.dve.sql.transform.execution.ComplexDDLExecutionStep; import com.tesora.dve.sql.transform.execution.ExecutionSequence; import com.tesora.dve.sql.transform.execution.CatalogModificationExecutionStep.Action; import com.tesora.dve.worker.WorkerGroup; public class PEDropTenantStatement extends PEDropStatement<PETenant, Tenant> { private final StatementType countAs; public PEDropTenantStatement(Boolean ifExists, Persistable<PETenant, Tenant> targ, StatementType origStatementType) { super(PETenant.class, ifExists, true, targ, "TENANT"); countAs = origStatementType; } @Override public List<CatalogEntity> getDeleteObjects(SchemaContext pc) throws PEException { if (getTarget() != null) { // delete the children before the parent. the children is all the scoping records. Tenant t = getTarget().getPersistent(pc); return Collections.singletonList((CatalogEntity)t); } else return Collections.emptyList(); } @Override public void plan(SchemaContext pc, ExecutionSequence es, BehaviorConfiguration config) throws PEException { // for the target tenant, delete from all the tables that are visible PETenant tenant = (PETenant) getTarget(); ArrayList<TableScope> scopes = new ArrayList<TableScope>(tenant.getTableScopes(pc)); for(TableScope ts : scopes) { DeleteStatement ds = AdaptiveMultitenantSchemaPolicyContext.buildTenantDeleteFromTableStatement(pc, ts.getTable(pc), ts); ds.plan(pc,es, config); } es.append(new ComplexDDLExecutionStep(tenant.getDatabase(pc),tenant.getDatabase(pc).getDefaultStorage(pc),tenant, Action.DROP, new DropTenantCallback(pc,tenant))); } @Override public StatementType getStatementType() { if (countAs == null) return StatementType.UNIMPORTANT; return countAs; } private static class DropTenantCallback extends DDLCallback { private PETenant tenant; private SchemaContext context; private List<CatalogEntity> updates; private List<CatalogEntity> deletes; public DropTenantCallback(SchemaContext sc, PETenant pet) { tenant = pet; context= sc; } @Override public List<CatalogEntity> getUpdatedObjects() throws PEException { return updates; } @Override public List<CatalogEntity> getDeletedObjects() throws PEException { return deletes; } @Override public SQLCommand getCommand(CatalogDAO c) { return SQLCommand.EMPTY; } @Override public boolean canRetry(Throwable t) { return AdaptiveMultitenantSchemaPolicyContext.canRetry(t); } @Override public String description() { return System.identityHashCode(this) + "@DropTenantCallback for " + tenant.getName(); } @Override public void inTxn(SSConnection conn, WorkerGroup wg) throws PEException { updates = new ArrayList<CatalogEntity>(); deletes = new ArrayList<CatalogEntity>(); context.refresh(false); CatalogDAO c = conn.getCatalogDAO(); Tenant onTenant = tenant.getPersistent(context); c.refreshForLock(onTenant); deletes.add(onTenant); for(TableVisibility tv : onTenant.getScoping()) { UserTable ut = tv.getTable(); tv.setTable(null); updates.add(ut); Singletons.require(HostService.class).onGarbageEvent(); } } @Override public CacheInvalidationRecord getInvalidationRecord() { return new CacheInvalidationRecord(tenant.getCacheKey(), InvalidationScope.CASCADE); } @Override public boolean requiresFreshTxn() { return true; } @Override public boolean requiresWorkers() { // catalog only return false; } @Override public void postCommitAction(CatalogDAO c) { // TODO Auto-generated method stub } } }