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 com.tesora.dve.common.catalog.CatalogEntity; import com.tesora.dve.common.catalog.UserTrigger; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.sql.schema.PEAbstractTable.TableCacheKey; import com.tesora.dve.sql.schema.cache.CacheSegment; import com.tesora.dve.sql.schema.cache.SchemaCacheKey; import com.tesora.dve.sql.schema.cache.SchemaEdge; import com.tesora.dve.sql.statement.Statement; public class PETrigger extends Persistable<PETrigger, UserTrigger> { // triggers only make sense in the context of the target table, so no need for an edge // also, triggers are loaded/unloaded with the table private final PETable triggerTable; private final TriggerEvent triggerType; private String bodySrc; private String rawSQL; private SchemaEdge<PEUser> definer; private final TriggerTime when; private final SQLMode sqlMode; private final String collationConnection; private final String charsetConnection; private final String collationDatabase; public PETrigger(SchemaContext sc, Name name, PETable targetTable, Statement body, TriggerEvent triggerOn, PEUser user, String collationConnection, String charsetConnection, String collationDatabase, TriggerTime when, SQLMode sqlMode, String rawSQL) { super(buildCacheKey(name,targetTable)); setName(name.getUnqualified()); this.bodySrc = body.getSQL(sc); this.triggerTable = targetTable; this.triggerType = triggerOn; this.definer = StructuralUtils.buildEdge(sc,user,false); this.when = when; this.sqlMode = sqlMode; this.collationConnection = collationConnection; this.charsetConnection = charsetConnection; this.collationDatabase = collationDatabase; this.rawSQL = rawSQL; setPersistent(sc,null,null); } public PEUser getDefiner(SchemaContext sc) { return definer.get(sc); } public TriggerTime getTime() { return when; } public TriggerEvent getEvent() { return triggerType; } public PETable getTargetTable() { return triggerTable; } public String getBodySource() { return bodySrc; } public static PETrigger load(UserTrigger ut, SchemaContext sc, PETable onTable) { TriggerCacheKey tck = null; if (onTable == null) tck = buildCacheKey(ut.getName(),(TableCacheKey) PETable.getTableKey(ut.getTable())); else tck = buildCacheKey(ut.getName(), (TableCacheKey) onTable.getCacheKey()); PETrigger pep = (PETrigger) sc.getLoaded(ut,tck); if (pep == null) pep = new PETrigger(ut,sc,onTable); return pep; } public static PETrigger lookup(final SchemaContext sc, final Name triggerName, final Database<?> parentSchema) { return lookup(sc, triggerName.getUnqualified().get(), parentSchema.getName().get()); } private static PETrigger lookup(final SchemaContext sc, final String triggerName, final String parentSchemaName) { final UserTrigger ut = sc.getCatalog().findTrigger(triggerName, parentSchemaName); if (ut != null) { return PETrigger.load(ut, sc, null); } return null; } private PETrigger(UserTrigger ut, SchemaContext sc, PETable onTable) { super(buildCacheKey(ut.getName(), (TableCacheKey)(onTable == null ? PETable.getTableKey(ut.getTable()) : onTable.getCacheKey()))); sc.startLoading(this, ut); setName(new UnqualifiedName(ut.getName())); setPersistent(sc,ut,ut.getId()); PETable ttab = (onTable == null ? PETable.load(ut.getTable(), sc).asTable() : onTable); triggerTable = ttab; // do something with the body this.when = TriggerTime.valueOf(ut.getWhen()); this.triggerType = TriggerEvent.valueOf(ut.getEvent()); this.charsetConnection = ut.getCharsetConnection(); this.collationConnection = ut.getCollationConnection(); this.collationDatabase = ut.getDatabaseCollation(); if ("".equals(ut.getSQLMode())) this.sqlMode = null; else this.sqlMode = new SQLMode(ut.getSQLMode()); this.rawSQL = ut.getOrigSQL(); this.bodySrc = ut.getBody(); this.definer = StructuralUtils.buildEdge(sc,PEUser.load(ut.getDefiner(), sc),true); } public void setUser(SchemaContext sc, PEUser targ) { // transient because this should never be used on the persistent path this.definer = StructuralUtils.buildEdge(sc, targ, false); } @Override protected Class<? extends CatalogEntity> getPersistentClass() { return UserTrigger.class; } @Override protected int getID(UserTrigger p) { return p.getId(); } @Override protected UserTrigger lookup(SchemaContext sc) throws PEException { return null; } @Override protected UserTrigger createEmptyNew(SchemaContext sc) throws PEException { return new UserTrigger(getName().get(), bodySrc, triggerTable.persistTree(sc), triggerType.name(), when.name(), (sqlMode == null ? "" : sqlMode.toString()), charsetConnection, collationConnection, collationDatabase, definer.get(sc).persistTree(sc), rawSQL); } @Override protected void populateNew(SchemaContext sc, UserTrigger p) throws PEException { // does nothing } @Override protected Persistable<PETrigger, UserTrigger> load(SchemaContext sc, UserTrigger p) throws PEException { // TODO Auto-generated method stub return null; } @Override protected String getDiffTag() { return "trigger"; } public static TriggerCacheKey buildCacheKey(String triggerName, TableCacheKey onTable) { return new TriggerCacheKey(onTable, triggerName); } public static TriggerCacheKey buildCacheKey(Name trgName, PETable onTab) { return new TriggerCacheKey((TableCacheKey) onTab.getCacheKey(),trgName.getUnqualified().getUnquotedName().get()); } protected static class TriggerCacheKey extends SchemaCacheKey<PETrigger> { private final TableCacheKey targetTable; private final String triggerName; public TriggerCacheKey(TableCacheKey onTable, String trgName) { this.targetTable = onTable; this.triggerName = trgName; } // store triggers with tables public CacheSegment getCacheSegment() { return CacheSegment.TABLE; } @Override public int hashCode() { return addHash(initHash(PETrigger.class,triggerName.hashCode()),targetTable.hashCode()); } @Override public boolean equals(Object o) { if (o instanceof TriggerCacheKey) { TriggerCacheKey otck = (TriggerCacheKey) o; return otck.targetTable.equals(targetTable) && otck.triggerName.equals(triggerName); } return false; } @Override public PETrigger load(SchemaContext sc) { return lookup(sc, triggerName, targetTable.getDatabaseName()); } @Override public String toString() { return String.format("PETrigger:%s(%s)",triggerName,targetTable.toString()); } } }