package com.tesora.dve.sql.infoschema.direct; /* * #%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.List; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.persist.PersistedEntity; import com.tesora.dve.sql.infoschema.InfoView; import com.tesora.dve.sql.infoschema.InformationSchemaColumn; import com.tesora.dve.sql.infoschema.InformationSchemaException; import com.tesora.dve.sql.infoschema.InformationSchemaTable; import com.tesora.dve.sql.infoschema.persist.CatalogColumnEntity; import com.tesora.dve.sql.infoschema.persist.CatalogDatabaseEntity; import com.tesora.dve.sql.infoschema.persist.CatalogSchema; import com.tesora.dve.sql.infoschema.persist.CatalogTableEntity; import com.tesora.dve.sql.schema.ConnectionValues; import com.tesora.dve.sql.schema.Database; import com.tesora.dve.sql.schema.Lookup; import com.tesora.dve.sql.schema.Name; import com.tesora.dve.sql.schema.PEColumn; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.UnqualifiedName; import com.tesora.dve.sql.util.Cast; import com.tesora.dve.sql.util.Functional; import com.tesora.dve.sql.util.ResizableArray; import com.tesora.dve.sql.util.UnaryFunction; import com.tesora.dve.variables.KnownVariables; public class DirectInformationSchemaTable implements InformationSchemaTable { private final boolean privileged; private final boolean extension; private final InfoView view; private final Name name; // might be different than what is declared (i.e. case) private final Name pluralName; protected List<DirectInformationSchemaColumn> columns; protected Lookup<DirectInformationSchemaColumn> lookup; private final DirectInformationSchemaColumn identColumn; private final ResizableArray<DirectInformationSchemaColumn> orderByColumns; public static final String tenantVariable = "tenant"; public static final String metadataExtensions = "mdex"; public static final String sessid = "sessid"; public DirectInformationSchemaTable(SchemaContext sc, InfoView view, List<PEColumn> cols, UnqualifiedName tableName, UnqualifiedName pluralTableName, boolean privileged, boolean extension, List<DirectColumnGenerator> columnGenerators) { this.privileged = privileged; this.extension = extension; this.view = view; // load up our columns columns = new ArrayList<DirectInformationSchemaColumn>(); this.lookup = new Lookup<DirectInformationSchemaColumn>(columns, new UnaryFunction<Name[], DirectInformationSchemaColumn>() { @Override public Name[] evaluate(DirectInformationSchemaColumn object) { return new Name[] { object.getName() }; } }, false, view.isLookupCaseSensitive()); for(int i = 0; i < cols.size(); i++) { DirectColumnGenerator dcg = columnGenerators.get(i); PEColumn pec = cols.get(i); addColumn(sc,new DirectInformationSchemaColumn(view,pec.getName().getUnqualified(),pec, dcg.isIdent(),dcg.getOrderByOffset() > -1,dcg.isExtension(),dcg.isPrivilege(),dcg.isFull())); } this.name = (view.isCapitalizeNames() ? tableName.getCapitalized().getUnqualified() : tableName); if (pluralTableName == null) this.pluralName = pluralTableName; else this.pluralName = (view.isCapitalizeNames() ? pluralTableName.getCapitalized().getUnqualified() : pluralTableName); orderByColumns = new ResizableArray<DirectInformationSchemaColumn>(); DirectInformationSchemaColumn ic = null; for(DirectColumnGenerator dcg : columnGenerators) { if (dcg.getOrderByOffset() > -1) { orderByColumns.set(dcg.getOrderByOffset(),lookup.lookup(dcg.getName())); } if (ic == null && dcg.isIdent()) ic = lookup.lookup(dcg.getName()); } this.identColumn = ic; } @Override public InformationSchemaColumn addColumn(SchemaContext sc, InformationSchemaColumn c) { DirectInformationSchemaColumn cv = (DirectInformationSchemaColumn) c; cv.setPosition(columns.size()); columns.add(cv); lookup.refreshBacking(columns); cv.setTable(this); return cv; } @Override public List<InformationSchemaColumn> getColumns(SchemaContext sc) { return Functional.apply(columns, new Cast<InformationSchemaColumn,DirectInformationSchemaColumn>()); } @Override public DirectInformationSchemaColumn lookup(SchemaContext sc, Name n) { return lookup.lookup(n); } public DirectInformationSchemaColumn lookup(String n) { return lookup.lookup(new UnqualifiedName(n)); } @Override public Name getName(SchemaContext sc,ConnectionValues cv) { return name; } @Override public Name getPluralName() { return pluralName; } @Override public boolean isInfoSchema() { return true; } @Override public boolean isTempTable() { return false; } @SuppressWarnings("unchecked") @Override public Database<?> getDatabase(SchemaContext sc) { return ((Database<?>)sc.getSource().find(sc, view.getCacheKey())); } @Override public Name getName() { return name; } @Override public InfoView getView() { return view; } @Override public DirectInformationSchemaColumn getOrderByColumn() { if (orderByColumns.size() > 0) return orderByColumns.get(0); return null; } public ResizableArray<DirectInformationSchemaColumn> getOrderByColumns() { return orderByColumns; } @Override public DirectInformationSchemaColumn getIdentColumn() { return identColumn; } @Override public boolean requiresPriviledge() { return privileged; } @Override public boolean isExtension() { return extension; } @Override public boolean isVariablesTable() { // TODO Auto-generated method stub return false; } public void assertPermissions(SchemaContext sc) { if (!privileged) return; if (!sc.getPolicyContext().isRoot()) throw new InformationSchemaException("You do not have permissions to query " + getName().get()); } @Override public boolean isView() { return true; } public List<DirectInformationSchemaColumn> getProjectionColumns(boolean includeExtensions, boolean includePriviledged, boolean includeFull) { ArrayList<DirectInformationSchemaColumn> out = new ArrayList<DirectInformationSchemaColumn>(); for(DirectInformationSchemaColumn isc : columns) { if (!isc.isVisible()) continue; if (isc.isExtension() && !includeExtensions) continue; if (isc.requiresPrivilege() && !includePriviledged) continue; if (isc.isFull() && !includeFull) continue; out.add(isc); } return out; } protected boolean useExtensions(SchemaContext sc) { return KnownVariables.SHOW_METADATA_EXTENSIONS.getValue(sc.getConnection().getVariableSource()).booleanValue(); } @Override public void buildTableEntity(CatalogSchema cs, CatalogDatabaseEntity db, int dmid, int storageid, List<PersistedEntity> acc) throws PEException { buildTableEntity(cs,db,dmid,storageid,acc, Functional.apply(columns,new UnaryFunction<PEColumn,DirectInformationSchemaColumn>() { @Override public PEColumn evaluate( DirectInformationSchemaColumn object) { return object.getColumn(); } }), getName().getUnqualified()); } public static void buildTableEntity(CatalogSchema cs, CatalogDatabaseEntity db, int dmid, int storageid, List<PersistedEntity> acc, List<PEColumn> columns, UnqualifiedName tableName) throws PEException { CatalogTableEntity cte = new CatalogTableEntity(cs,db,tableName.get(),dmid,storageid,"MEMORY"); acc.add(cte); int counter = 0; for(PEColumn pec : columns) { CatalogColumnEntity cce = new CatalogColumnEntity(cs,cte); cce.setName(pec.getName().get()); cce.setNullable(pec.isNullable()); cce.setType(pec.getType()); cce.setPosition(counter); acc.add(cce); } } }