package com.tesora.dve.sql.transform; /* * #%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.HashSet; import java.util.List; import com.tesora.dve.sql.node.expression.ColumnInstance; import com.tesora.dve.sql.node.expression.ConstantExpression; import com.tesora.dve.sql.node.expression.ExpressionNode; import com.tesora.dve.sql.node.expression.TableInstance; import com.tesora.dve.sql.schema.Column; import com.tesora.dve.sql.schema.DistributionKey; import com.tesora.dve.sql.schema.PEAbstractTable; import com.tesora.dve.sql.schema.PEColumn; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.cache.IParameter; import com.tesora.dve.sql.util.ListOfPairs; public abstract class TransformKey { // the containing expression protected ExpressionNode containing; protected TransformKey(ExpressionNode containing) { this.containing = containing; } public ExpressionNode getContaining() { return containing; } public abstract List<TransformKeySimple> getKeySource(); public abstract boolean valid(SchemaContext sc); public abstract TableInstance getTable(); public abstract boolean hasParameterizedValues(); public static class TransformKeySimple extends TransformKey { protected List<TransformKeyValueColumn> values; protected TableInstance onTable; public TransformKeySimple(ExpressionNode containing, ColumnInstance col, ConstantExpression lit) { super(containing); values = new ArrayList<TransformKeyValueColumn>(); values.add(new TransformKeyValueColumn(col, lit)); onTable = col.getTableInstance(); } public TransformKeySimple(ExpressionNode containing, List<TransformKeySimple> composedOf) { super(containing); values = new ArrayList<TransformKeyValueColumn>(); for(TransformKeySimple tks : composedOf) values.addAll(tks.getValues()); onTable = values.get(0).getTable(); } public List<TransformKeyValueColumn> getValues() { return values; } @Override public boolean hasParameterizedValues() { for(TransformKeyValueColumn tkvc : values) if (tkvc.isParameterized()) return true; return false; } @Override public TableInstance getTable() { return onTable; } @Override public List<TransformKeySimple> getKeySource() { return Collections.singletonList(this); } @Override public boolean valid(SchemaContext sc) { TableInstance ti = null; HashSet<Column<?>> columns = new HashSet<Column<?>>(); for(TransformKeyValueColumn c : values) { columns.add(c.getColumn().getColumn()); if (ti == null) ti = c.getTable(); else if (ti != c.getTable()) return false; } if (!columns.equals(ti.getAbstractTable().getDistributionVector(sc).getColumns(sc))) return false; return true; } public DistributionKey buildKeyValue(SchemaContext sc) { PEAbstractTable<?> tab = onTable.getAbstractTable(); ListOfPairs<PEColumn,ConstantExpression> vect = new ListOfPairs<PEColumn,ConstantExpression>(); for(TransformKeyValueColumn vc : values) vect.add(vc.getColumn().getPEColumn(),vc.getLiteral()); DistributionKey kv = tab.getDistributionVector(sc).buildDistKey(sc, onTable.getTableKey(), vect); return kv; } } // a series key involves many actual key values public static class TransformKeySeries extends TransformKey { protected List<TransformKeySimple> parts; public TransformKeySeries(ExpressionNode containing, List<TransformKeySimple> parts) { super(containing); this.parts = parts; } @Override public List<TransformKeySimple> getKeySource() { return parts; } @Override public boolean hasParameterizedValues() { for(TransformKeySimple tks : parts) if (tks.hasParameterizedValues()) return true; return false; } @Override public boolean valid(SchemaContext sc) { boolean valid = true; TableInstance ti = null; for(TransformKeySimple tks : parts) { if (!tks.valid(sc)) { valid = false; break; } else if (ti == null) ti = tks.getTable(); else if (ti != tks.getTable()) { valid = false; break; } } return valid; } @Override public TableInstance getTable() { return parts.get(0).getTable(); } } public static class TransformKeyValueColumn { protected ColumnInstance column; protected ConstantExpression literal; public TransformKeyValueColumn(ColumnInstance ci, ConstantExpression lit) { column = ci; literal = lit; } public ColumnInstance getColumn() { return column; } public TableInstance getTable() { return column.getTableInstance(); } public ConstantExpression getLiteral() { return literal; } public boolean isParameterized() { return literal instanceof IParameter; } } }