package com.tesora.dve.sql.schema.mt; /* * #%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.Collection; import com.tesora.dve.common.catalog.CatalogEntity; import com.tesora.dve.common.catalog.TableVisibility; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.lockmanager.LockSpecification; import com.tesora.dve.sql.schema.HasName; import com.tesora.dve.sql.schema.HasTable; import com.tesora.dve.sql.schema.Name; import com.tesora.dve.sql.schema.PEAbstractTable; import com.tesora.dve.sql.schema.PETable; import com.tesora.dve.sql.schema.Persistable; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.StructuralUtils; import com.tesora.dve.sql.schema.TableUseLock; import com.tesora.dve.sql.schema.UnqualifiedName; 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.schema.mt.PETenant.TenantCacheKey; public class TableScope extends Persistable<TableScope, TableVisibility> implements HasName, HasTable { protected SchemaEdge<PETenant> tenant; protected SchemaEdge<PEAbstractTable<?>> table; protected Long autoIncrStart; protected Integer autoIncID; @SuppressWarnings("unchecked") public TableScope(SchemaContext sc, PETable tab, PETenant ten, Long autoIncrFirstValue, Name name) { super(getScopeKey(ten,name)); tenant = StructuralUtils.buildEdge(sc,ten, false); table = StructuralUtils.buildEdge(sc,tab,false); if (name != null) setName(name); else setName(tab.getName()); autoIncrStart = autoIncrFirstValue; } public String toString(SchemaContext sc) { StringBuilder buf = new StringBuilder(); buf.append("scope{tenant=").append(tenant.get(sc).getName()) .append(",name=").append(getName().getSQL()) .append(",table=").append(table.get(sc).getName().getSQL()); buf.append("}"); return buf.toString(); } @Override public String toString() { return toString(SchemaContext.threadContext.get()); } public PETable getTable(SchemaContext sc) { return (PETable) table.get(sc); } public SchemaCacheKey<PEAbstractTable<?>> getTableKey() { return table.getCacheKey(); } public PETenant getTenant(SchemaContext sc) { return tenant.get(sc); } public TableUseLock getLock(String why, SchemaContext sc) { return new TableUseLock(why,tenant.get(sc).getCacheKey().toString(), getName().getUnquotedName().get()); } @SuppressWarnings("unchecked") public void setTable(SchemaContext sc, PETable pet) { table = StructuralUtils.buildEdge(sc,pet, false); } public static TableScope load(TableVisibility tv, SchemaContext sc) { TableScope ts = (TableScope)sc.getLoaded(tv,getScopeKey(tv)); if (ts == null) ts = new TableScope(tv, sc); return ts; } @SuppressWarnings("unchecked") private TableScope(TableVisibility tv, SchemaContext sc) { super(getScopeKey(tv)); sc.startLoading(this, tv); tenant = StructuralUtils.buildEdge(sc,PETenant.load(tv.getTenant(), sc),true); table = StructuralUtils.buildEdge(sc,PETable.load(tv.getTable(), sc),true); if (tv.getLocalName() != null) setName(new UnqualifiedName(tv.getLocalName())); else setName(table.get(sc).getName()); if (tv.hasAutoIncr()) autoIncID = tv.getAutoIncr().getId(); setPersistent(sc,tv,tv.getId()); sc.finishedLoading(this, tv); } public static TableScope load(HollowTableVisibility htv, SchemaContext sc) { TableScope ts = (TableScope)sc.getSource().getLoaded(buildRawKey(htv)); if (ts == null) ts = new TableScope(htv,sc); return ts; } private static ScopeCacheKey buildRawKey(HollowTableVisibility htv) { return new ScopeCacheKey(new TenantCacheKey(htv.getTenantName(),htv.getTenantID()),htv.getLocalName()); } private TableScope(HollowTableVisibility htv, SchemaContext sc) { super(buildRawKey(htv)); setName(new UnqualifiedName(htv.getLocalName())); ScopeCacheKey sck = (ScopeCacheKey) getCacheKey(); SchemaCacheKey<PETenant> tck = sck.getTenantCacheKey(); tenant = sc.buildEdgeFromKey(tck, true); SchemaCacheKey<PEAbstractTable<?>> backingTable = new TableCacheKey(htv.getDbid(), htv.getDbName(), new UnqualifiedName(htv.getTabName())); table = sc.buildEdgeFromKey(backingTable, true); autoIncID = htv.getAutoIncrementId(); persistentID = htv.getScopeID(); sc.getSource().setLoaded(this, sc.isCacheLoading(sck) ? null : sck); } @Override protected Class<? extends CatalogEntity> getPersistentClass() { return TableVisibility.class; } @Override protected TableVisibility lookup(SchemaContext pc) throws PEException { Integer tabID = table.get(pc).getPersistentID(); Integer tenID = tenant.get(pc).getPersistentID(); if (tenID == null || tabID == null) return null; return pc.getCatalog().findVisibilityRecord(tabID.intValue(), tenID.intValue()); } @Override protected TableVisibility createEmptyNew(SchemaContext pc) throws PEException { String name = (getName().equals(table.get(pc).getName()) ? null : getName().get()); return new TableVisibility(tenant.get(pc).persistTree(pc), table.get(pc).persistTree(pc), name, autoIncrStart); } @Override protected void populateNew(SchemaContext pc, TableVisibility p) throws PEException { } @Override protected void updateExisting(SchemaContext pc, TableVisibility tv) throws PEException { tv.setTable(table.get(pc).persistTree(pc)); } @Override protected Persistable<TableScope, TableVisibility> load(SchemaContext pc, TableVisibility p) throws PEException { return new TableScope(p, pc); } @Override protected int getID(TableVisibility p) { return p.getId(); } @Override public Persistable<TableScope, TableVisibility> reload(SchemaContext usingContext) throws PEException { TableVisibility tv = lookup(usingContext); return new TableScope(tv, usingContext); } @Override protected String getDiffTag() { return "TableScope"; } public static ScopeCacheKey getScopeKey(PETenant onTenant, Name onName) { return getScopeKey((TenantCacheKey) onTenant.getCacheKey(), onName.getUnquotedName().getUnqualified().get()); } public static ScopeCacheKey getScopeKey(TenantCacheKey tenantKey, String name) { return new ScopeCacheKey(tenantKey,name); } public static SchemaCacheKey<TableScope> getScopeKey(TableVisibility tv) { return getScopeKey((TenantCacheKey)PETenant.getTenantKey(tv.getTenant()),(tv.getLocalName() != null ? tv.getLocalName() : tv.getTable().getName())); } public static class ScopeCacheKey extends SchemaCacheKey<TableScope> { private static final long serialVersionUID = 1L; private final TenantCacheKey tenantKey; private String name; public ScopeCacheKey(TenantCacheKey tenKey, String forName) { super(); this.tenantKey = tenKey; this.name = forName; } @Override public int hashCode() { return addHash(initHash(TableScope.class,tenantKey.getTenantName().hashCode()),name.hashCode()); } @Override public String toString() { return "TableScope:" + tenantKey.getTenantName() + "/" + name; } @Override public boolean equals(Object o) { if (o instanceof ScopeCacheKey) { ScopeCacheKey sck = (ScopeCacheKey) o; return this.tenantKey.equals(sck.tenantKey) && this.name.equals(sck.name); } return false; } @Override public TableScope load(SchemaContext sc) { // if it's not a persistent catalog we have to get the whole object // likewise if it's a mutable source we're doing ddl - need the whole object if (sc.isMutableSource() || !sc.getCatalog().isPersistent()) { TableVisibility tv = sc.getCatalog().findTableVisibility(tenantKey.getTenantName(), tenantKey.getTenantID(), name); if (tv == null) return null; return TableScope.load(tv, sc); } else { HollowTableVisibility htv = sc.getCatalog().findHollowTableVisibility(tenantKey.getTenantName(), tenantKey.getTenantID(), name); if (htv == null) return null; return TableScope.load(htv, sc); } } @Override public CacheSegment getCacheSegment() { return CacheSegment.SCOPE; } public SchemaCacheKey<PETenant> getTenantCacheKey() { return tenantKey; } @Override public Collection<SchemaCacheKey<?>> getCascades(Object obj) { TableScope ts = (TableScope) obj; ArrayList<SchemaCacheKey<?>> others = new ArrayList<SchemaCacheKey<?>>(); others.add(ts.table.getCacheKey()); return others; } @Override public SchemaCacheKey<?> getEnclosing() { return tenantKey; } @Override public LockSpecification getLockSpecification(String why) { return new TableUseLock(why,tenantKey.toString(),name); } } public Integer getAutoIncrementID() { return autoIncID; } public static boolean valid(TableVisibility tv) { if (tv.getTable() == null) return false; if (tv.getTenant() == null) return false; return PETable.valid(tv.getTable()); } }