package com.tesora.dve.sql.infoschema; /* * #%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 java.util.Properties; import com.tesora.dve.charset.MysqlNativeCollation; import com.tesora.dve.common.DBHelper; import com.tesora.dve.common.PEConstants; import com.tesora.dve.common.catalog.CatalogDAO; import com.tesora.dve.common.catalog.FKMode; import com.tesora.dve.common.catalog.MultitenantMode; import com.tesora.dve.common.catalog.TemplateMode; import com.tesora.dve.common.catalog.UserDatabase; import com.tesora.dve.db.DBNative; import com.tesora.dve.errmap.ErrorMapper; import com.tesora.dve.errmap.FormattedErrorInfo; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.exceptions.PEMappedRuntimeException; import com.tesora.dve.persist.PersistedEntity; import com.tesora.dve.singleton.Singletons; import com.tesora.dve.sql.infoschema.direct.DirectSchemaBuilder; import com.tesora.dve.sql.infoschema.persist.CatalogCollationEntity; import com.tesora.dve.sql.infoschema.persist.CatalogSchema; import com.tesora.dve.sql.infoschema.spi.CatalogGenerator; import com.tesora.dve.sql.parser.InvokeParser; import com.tesora.dve.sql.parser.ParserOptions; import com.tesora.dve.sql.schema.Name; import com.tesora.dve.sql.schema.PEDatabase; import com.tesora.dve.sql.schema.PEPersistentGroup; import com.tesora.dve.sql.schema.PEStorageSite; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.UnqualifiedName; import com.tesora.dve.sql.statement.Statement; import com.tesora.dve.sql.statement.ddl.DDLStatement; import com.tesora.dve.sql.statement.ddl.PECreateTableStatement; import com.tesora.dve.sql.transexec.spi.TransientEngine; import com.tesora.dve.sql.transexec.spi.TransientEngineFactory; import com.tesora.dve.sql.transform.execution.CatalogModificationExecutionStep; import com.tesora.dve.sql.util.Pair; public final class InformationSchemas implements InformationSchemaService { protected final InformationSchema infoSchema; protected final ShowView show; protected final MysqlSchema mysql; protected final PEDatabase catalog; private InformationSchemas(InformationSchema isv, ShowView sv, MysqlSchema msv, PEDatabase pdb) { this.infoSchema = isv; this.show = sv; this.mysql = msv; this.catalog = pdb; } @Override public InformationSchema getInfoSchema() { return infoSchema; } @Override public PEDatabase getCatalogSchema() { return this.catalog; } @Override public ShowView getShowSchema() { return this.show; } @Override public ShowSchemaBehavior lookupShowTable(UnqualifiedName unq) { return getShowSchema().lookupTable(unq); } @Override public MysqlSchema getMysqlSchema() { return this.mysql; } @Override public List<PersistedEntity> buildEntities(int groupid, int modelid, String charSet, String collation) throws PEException { CatalogSchema cs = new CatalogSchema(); ArrayList<PersistedEntity> acc = new ArrayList<PersistedEntity>(); for (final MysqlNativeCollation entry : MysqlNativeCollation.supportedCollations) { acc.add(new CatalogCollationEntity(cs, entry)); } infoSchema.buildEntities(cs,groupid, modelid, charSet, collation, acc); show.buildEntities(cs, groupid, modelid, charSet, collation, acc); mysql.buildEntities(cs, groupid, modelid, charSet, collation, acc); return acc; } public static InformationSchemas build(DBNative dbn, CatalogDAO c, Properties props) throws PEException { try { InformationSchema informationSchema = new InformationSchema(); ShowView showSchema = new ShowView(); MysqlSchema mysqlSchema = new MysqlSchema(); PEDatabase catSchema = buildCatalogSchema(c,dbn,props); // make the builders for each schema & then build them. InformationSchemaBuilder builders[] = new InformationSchemaBuilder[] { // the order these are built in is important new DirectSchemaBuilder(catSchema) }; for(InformationSchemaBuilder isb : builders) isb.populate(informationSchema, showSchema, mysqlSchema, dbn); return new InformationSchemas(informationSchema,showSchema,mysqlSchema, catSchema); } catch (PEException pe) { throw pe; } catch (PEMappedRuntimeException se) { FormattedErrorInfo fei = ErrorMapper.makeResponse(se); throw new PEException("Unable to initialize information schema: " + (fei == null ? se.getMessage() : fei.getErrorMessage()), se); } catch (Throwable t) { throw new PEException("Unable to initialize information schema",t); } } @Override public InformationSchemaDatabase buildPEDatabase(SchemaContext sc, UserDatabase udb) { if (InfoView.INFORMATION.getUserDatabaseName().equals(udb.getName())) return new InformationSchemaDatabase(sc, udb, infoSchema); else if (InfoView.MYSQL.getUserDatabaseName().equals(udb.getName())) return new InformationSchemaDatabase(sc, udb, mysql); return null; } private static PEDatabase buildCatalogSchema(CatalogDAO c, DBNative dbn, Properties catalogProps) throws Throwable { if (c == null) return null; // for now String database = catalogProps.getProperty(DBHelper.CONN_DBNAME, PEConstants.CATALOG); TransientEngine tee = Singletons.require(TransientEngineFactory.class).create(database,dbn.getTypeCatalog()); ParserOptions opts = ParserOptions.TEST.setResolve().setIgnoreMissingUser(); SchemaContext sc = tee.getPersistenceContext(); PEPersistentGroup catalogGroup = new PEPersistentGroup(sc,new UnqualifiedName(PEConstants.SYSTEM_GROUP_NAME), Collections.<PEStorageSite> emptyList()); PEDatabase pdb = new PEDatabase(sc,new UnqualifiedName(database),catalogGroup,new Pair<Name,TemplateMode>(null, TemplateMode.OPTIONAL), MultitenantMode.OFF, FKMode.STRICT, "",""); pdb.setID(-1); tee.setCurrentDatabase(pdb); CatalogGenerator generator = Singletons.require(CatalogGenerator.class); String[] decls = generator.buildCreateCurrentSchema(c,catalogProps); for(String s : decls) { if (s.startsWith("create")) { sc.refresh(true); List<Statement> stmts = InvokeParser.parse(InvokeParser.buildInputState(s,sc), opts, sc).getStatements(); for(Statement stmt : stmts) { DDLStatement ddl = (DDLStatement) stmt; if (ddl.getAction() == CatalogModificationExecutionStep.Action.CREATE) { PECreateTableStatement pects = (PECreateTableStatement) stmt; pdb.getSchema().addTable(sc, pects.getTable()); } } } } pdb.setNameMangling(false); return pdb; } }