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.HashMap;
import java.util.List;
import com.tesora.dve.db.DBNative;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.resultset.ColumnMetadata;
import com.tesora.dve.resultset.ColumnSet;
import com.tesora.dve.resultset.IntermediateResultSet;
import com.tesora.dve.resultset.ResultRow;
import com.tesora.dve.server.global.HostService;
import com.tesora.dve.singleton.Singletons;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.expression.MTTableKey;
import com.tesora.dve.sql.expression.ScopeEntry;
import com.tesora.dve.sql.expression.TableKey;
import com.tesora.dve.sql.infoschema.InfoView;
import com.tesora.dve.sql.infoschema.InformationSchemaException;
import com.tesora.dve.sql.infoschema.ShowOptions;
import com.tesora.dve.sql.node.expression.ExpressionNode;
import com.tesora.dve.sql.node.expression.TableInstance;
import com.tesora.dve.sql.schema.LockInfo;
import com.tesora.dve.sql.schema.Name;
import com.tesora.dve.sql.schema.PEAbstractTable;
import com.tesora.dve.sql.schema.PEColumn;
import com.tesora.dve.sql.schema.PEForeignKey;
import com.tesora.dve.sql.schema.PEKey;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.schema.UnqualifiedName;
import com.tesora.dve.sql.schema.modifiers.AutoincTableModifier;
import com.tesora.dve.sql.statement.Statement;
import com.tesora.dve.sql.statement.ddl.SchemaQueryStatement;
import com.tesora.dve.variables.KnownVariables;
public class DirectShowCreateTable extends DirectShowSchemaTable {
public DirectShowCreateTable(SchemaContext sc,
List<PEColumn> cols, List<DirectColumnGenerator> columnGenerators) {
super(sc, InfoView.SHOW, cols, new UnqualifiedName("create table"), null, false, false,
columnGenerators);
// TODO Auto-generated constructor stub
}
@Override
public Statement buildShowPlural(SchemaContext sc, List<Name> scoping,
ExpressionNode likeExpr, ExpressionNode whereExpr,
ShowOptions options) {
throw new InformationSchemaException("Illegal operation: show create table does not support multiple targets");
}
@Override
public Statement buildUniqueStatement(SchemaContext sc, Name onName,
ShowOptions opts) {
TableInstance tab = sc.getTemporaryTableSchema().buildInstance(sc, onName);
// delegate to the table table to get the basic information
try {
sc.getCatalog().startTxn();
// build a tschema version so we can massage the definition to add back in the stuff we stripped out
// and remove the stuff we added
PEAbstractTable<?> tschema = null;
LockInfo lock = new LockInfo(com.tesora.dve.lockmanager.LockType.RSHARED, "show create table");
if (tab == null) {
tab = ScopeEntry.resolver.lookupTable(sc, onName, lock);
if (tab == null)
throw new SchemaException(Pass.SECOND, "No such table: " + onName);
}
tschema = tab.getAbstractTable().recreate(sc, tab.getAbstractTable().getDeclaration(), lock);
StringBuilder buf = new StringBuilder();
TableKey tk = tab.getTableKey();
if (sc.getPolicyContext().isSchemaTenant() || sc.getPolicyContext().isDataTenant()) {
Name localName = null;
if (tab.getTableKey() instanceof MTTableKey) {
MTTableKey mttk = (MTTableKey) tab.getTableKey();
localName = mttk.getScope().getName();
}
if (localName != null)
tschema.setName(localName);
HashMap<UnqualifiedName,UnqualifiedName> fkmap = new HashMap<UnqualifiedName,UnqualifiedName>();
/*
if (ut != null) {
for(Key k : ut.getKeys()) {
// either not a foreign key, or a forward foreign key
// if forward we would have used the original declared name.
if (k.getReferencedTable() == null) continue;
Name visibleName = sc.getPolicyContext().getLocalName(k.getReferencedTable());
fkmap.put(new UnqualifiedName(k.getReferencedTable().getName()),visibleName.getUnqualified());
}
}
*/
// in mt mode the stored declaration has the mtid; remove it.
PEColumn c = tschema.getTenantColumn(sc);
tschema.removeColumn(sc,c);
if (tschema.isTable() && !tschema.isUserlandTemporaryTable()) {
List<PEKey> toRemove = new ArrayList<PEKey>();
for(PEKey k : tschema.getKeys(sc)) {
if (k.isHidden()) {
toRemove.add(k);
continue;
}
if (k.containsColumn(c)) {
k.removeColumn(c);
}
if (k.isForeign()) {
PEForeignKey pefk = (PEForeignKey) k;
// also reset the physical symbol name to be the logical symbol name
pefk.setPhysicalSymbol(pefk.getSymbol());
if (pefk.isForward()) continue;
UnqualifiedName repl = fkmap.get(pefk.getTargetTableName(null));
pefk.revertToForward(sc);
pefk.resetTargetTableName(repl);
}
}
for(PEKey k : toRemove) {
tschema.asTable().removeKey(sc, k);
}
}
}
if (tk.getAbstractTable().isTable()) {
long nextVal = -1;
if (tk.getAbstractTable().asTable().hasAutoInc())
nextVal = tk.readAutoIncrBlock(sc);
if (nextVal > 1)
tschema.asTable().getModifiers().setModifier(new AutoincTableModifier(nextVal));
}
boolean omitDistVect =
KnownVariables.OMIT_DIST_COMMENTS.getValue(sc.getConnection().getVariableSource()).booleanValue();
if (tschema.isTable())
buf.append(Singletons.require(DBNative.class).getEmitter().emitExternalCreateTableStatement(sc,sc.getValues(),tschema.asTable(),omitDistVect));
else {
buf.append("CREATE ");
Singletons.require(DBNative.class).getEmitter().emitViewDeclaration(sc, sc.getValues(), tschema.asView().getView(sc), null, buf);
}
ColumnSet cs = new ColumnSet();
try {
String varcharTypeName = Singletons.require(DBNative.class).getTypeCatalog().findType(java.sql.Types.VARCHAR, true).getTypeName();
cs.addColumn(buildColumnMetadata(tschema.isTable() ? "Table" : "View",255,varcharTypeName, java.sql.Types.VARCHAR));
cs.addColumn(buildColumnMetadata(tschema.isTable() ? "Create Table" : "Create View",255,varcharTypeName, java.sql.Types.VARCHAR));
if (tschema.isView()) {
cs.addColumn(buildColumnMetadata("character_set_client",255,varcharTypeName,java.sql.Types.VARCHAR));
cs.addColumn(buildColumnMetadata("collation_connection",255,varcharTypeName,java.sql.Types.VARCHAR));
}
} catch (PEException pe) {
throw new SchemaException(Pass.PLANNER, "Unable to find varchar type?",pe);
}
ResultRow rr = new ResultRow();
rr.addResultColumn(onName.getUnqualified().get());
rr.addResultColumn(buf.toString());
if (tschema.isView()) {
rr.addResultColumn(tschema.asView().getView(sc).getCharset().getUnquotedName().get());
rr.addResultColumn(tschema.asView().getView(sc).getCollation().getUnquotedName().get());
}
return new SchemaQueryStatement(false, getName().get(),new IntermediateResultSet(cs,rr));
} finally {
sc.getCatalog().rollbackTxn();
}
}
private static ColumnMetadata buildColumnMetadata(String name, int size, String typeName, int typeCode) {
ColumnMetadata cmc = new ColumnMetadata();
cmc.setName(name);
cmc.setSize(size);
cmc.setTypeName(typeName);
cmc.setDataType(typeCode);
cmc.setAliasName(name);
return cmc;
}
}