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.List; import com.tesora.dve.common.catalog.CatalogEntity; import com.tesora.dve.common.catalog.DistributionModel; import com.tesora.dve.common.catalog.StorageGroup; import com.tesora.dve.db.Emitter.EmitOptions; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.queryplan.*; import com.tesora.dve.resultset.ProjectionInfo; import com.tesora.dve.server.messaging.SQLCommand; import com.tesora.dve.sql.schema.*; import com.tesora.dve.sql.schema.cache.CacheInvalidationRecord; import com.tesora.dve.sql.schema.cache.InvalidationScope; import com.tesora.dve.sql.util.Functional; public class SimpleDDLExecutionStep extends CatalogModificationExecutionStep { protected List<CatalogEntity> deletes; protected List<CatalogEntity> updates; protected SQLCommand sql; private Boolean commitOverride = null; protected CacheInvalidationRecord invalidationRecord; public SimpleDDLExecutionStep(PEDatabase db, PEStorageGroup tsg, Persistable<?, ?> root, Action act, SQLCommand sql, List<CatalogEntity> deleteList, List<CatalogEntity> entityList, CacheInvalidationRecord invalidate) { super(db, tsg, root, act); this.deletes = deleteList; this.updates = entityList; this.invalidationRecord = invalidate; this.sql = sql; } public SimpleDDLExecutionStep withCommitOverride(boolean v) { setCommitOverride(v); return this; } public List<CatalogEntity> getEntities() { return updates; } public List<CatalogEntity> getDeletes() { return deletes; } protected QueryStepDDLOperation buildOperation(SchemaContext sc, ConnectionValues cv) throws PEException { QueryStepDDLOperation qso = new QueryStepDDLOperation(getStorageGroup(sc,cv), getPersistentDatabase(), sql,getCacheInvalidation(sc)); if (getCommitOverride() != null) return (QueryStepDDLOperation) qso.withCommitOverride(getCommitOverride()); return qso; } @Override public void schedule(ExecutionPlanOptions opts, List<QueryStepOperation> qsteps, ProjectionInfo projection, SchemaContext sc, ConnectionValuesMap cvm, ExecutionPlan containing) throws PEException { ConnectionValues cv = cvm.getValues(containing); StorageGroup sg = getStorageGroup(sc,cv); if (rootEntity instanceof PEDatabase) { PEDatabase db = (PEDatabase)rootEntity; CacheInvalidationRecord invalidate = new CacheInvalidationRecord(db.getCacheKey(), (((action == Action.DROP) || (action == Action.ALTER)) ? InvalidationScope.CASCADE : InvalidationScope.LOCAL)); if (action == Action.CREATE) { qsteps.add(new QueryStepCreateDatabaseOperation(sg, db.getPersistent(sc),invalidate)); return; } else if (action == Action.DROP) { qsteps.add(new QueryStepDropDatabaseOperation(sg, db.getPersistent(sc),invalidate)); return; } else if (action == Action.ALTER) { qsteps.add(new QueryStepAlterDatabaseOperation(sg, db.getPersistent(sc), invalidate)); return; } } else if (rootEntity instanceof PEUser) { PEUser peu = (PEUser) rootEntity; CacheInvalidationRecord invalidate = new CacheInvalidationRecord(peu.getCacheKey(),InvalidationScope.LOCAL); if (action == Action.CREATE) { qsteps.add(new QueryStepCreateUserOperation(sg, peu.getPersistent(sc),invalidate)); return; } } else if (rootEntity instanceof PEPriviledge) { PEPriviledge priv = (PEPriviledge)rootEntity; if (action == Action.ALTER) { // if the priviledge is a global priviledge, we can just do a regular ddl operation // but if it is for a specific database/tenant, we have to do a grant priv operation if (!priv.isGlobal()) qsteps.add(new QueryStepGrantPrivilegesOperation(sg, priv.getPersistent(sc),getCacheInvalidation(sc))); } } QueryStepDDLOperation qso; if (rootEntity instanceof PETable){ PETable tab = (PETable)rootEntity; DistributionModel optionalDistModel = tab.getDistributionVector(sc).getModel().getSingleton(); qso = new QueryStepDDLOperation(sg,getPersistentDatabase(),sql,getCacheInvalidation(sc),action,optionalDistModel); } else qso = buildOperation(sc,cv); for(CatalogEntity ce : getEntities()) { qso.addCatalogUpdate(ce); } for(CatalogEntity ce : getDeletes()) { qso.addCatalogDeletion(ce); } qsteps.add(qso); } @Override public void display(SchemaContext sc, ConnectionValuesMap cvm, ExecutionPlan containing, List<String> buf, String indent, EmitOptions opts) { super.display(sc, cvm, containing, buf, indent, opts); // drops might not have a root entity if (rootEntity == null) buf.add(indent + " DDL " + action.name()); else { buf.add(indent + " DDL " + action.name() + " on " + rootEntity.getName() + " (type " + rootEntity.getClass().getName() + "): " + rootEntity); buf.add(indent + "updates: {" + Functional.joinToString(getEntities(), ",") + "}"); buf.add(indent + "deletes: {" + Functional.joinToString(getDeletes(), ",") + "}"); } } @Override public void getSQL(SchemaContext sc, ConnectionValuesMap cvm, ExecutionPlan containing, List<String> buf, EmitOptions opts) { buf.add(sql.getRawSQL()); } @Override public CacheInvalidationRecord getCacheInvalidation(SchemaContext sc) { return invalidationRecord; } public Boolean getCommitOverride() { return commitOverride; } private void setCommitOverride(Boolean commitOverride) { this.commitOverride = commitOverride; } }