/* * Copyright (c) 2011-2015 EPFL DATA Laboratory * Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE) * * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ch.epfl.data.squall.api.sql.optimizers.name; import java.util.List; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.schema.Column; import org.apache.log4j.Logger; import ch.epfl.data.squall.api.sql.schema.ColumnNameType; import ch.epfl.data.squall.api.sql.util.ParserUtil; import ch.epfl.data.squall.api.sql.util.TupleSchema; import ch.epfl.data.squall.types.Type; /* * Expressions are being translated to columns from TupleSchema * This is explicitly done only in contains and indexOf because all the other methods from this classs call it. */ public class NameTranslator { private static Logger LOG = Logger.getLogger(NameTranslator.class); private final String _compName; // the name of the component which created // it, // used only for printing error messages public NameTranslator(String compName) { _compName = compName; } /* * WRAPPER methods */ public boolean contains(TupleSchema tupleSchema, Expression expr) { if (indexOf(tupleSchema.getSchema(), ParserUtil.getStringExpr(expr)) != ParserUtil.NOT_FOUND) // worked out without using synonims return true; translateExpr(tupleSchema, expr); // if after changing synonims still not found, return false return indexOf(tupleSchema.getSchema(), ParserUtil.getStringExpr(expr)) != ParserUtil.NOT_FOUND; } /* * This method differs from getColumnIndex since it might return * ParserUtil.NOT_FOUND (and user know how to deal with it) * tupleSchema.getSchema() contains a list of TableAlias.ColumnName */ public int getColumnIndex(TupleSchema tupleSchema, Column column) { final int index = indexOf(tupleSchema, column); if (index == ParserUtil.NOT_FOUND) { final String colStr = ParserUtil.getStringExpr(column); LOG.error("Column " + colStr + " cannot be found in " + _compName + " !"); } return index; } /* * List<ColumnNameType> is a user schema with full names * (TableAlias.ColumnName) For a field N1.NATIONNAME, columnName is * N1.NATIONNAME */ public Type getType(TupleSchema tupleSchema, Expression expr) { final int index = indexOf(tupleSchema, expr); if (index == ParserUtil.NOT_FOUND) { final String exprStr = ParserUtil.getStringExpr(expr); throw new RuntimeException("No column " + exprStr + " in tupleSchema!"); } return tupleSchema.getSchema().get(index).getType(); } /* * ORIGINAL private methods For a field N1.NATIONNAME, columnName is * N1.NATIONNAME List<ColumnNameType> is a user schema with full names * (TableAlias.ColumnName) */ private int indexOf(List<ColumnNameType> tupleSchema, String columnName) { for (int i = 0; i < tupleSchema.size(); i++) if (tupleSchema.get(i).getName().equals(columnName)) return i; return ParserUtil.NOT_FOUND; } /* * */ public int indexOf(TupleSchema tupleSchema, Expression expr) { final int index = indexOf(tupleSchema.getSchema(), ParserUtil.getStringExpr(expr)); if (index != ParserUtil.NOT_FOUND) // worked out without using synonims return index; translateExpr(tupleSchema, expr); // if after changing synonims still not found, return // ParserUtil.NOT_FOUND return indexOf(tupleSchema.getSchema(), ParserUtil.getStringExpr(expr)); } /* * TRANSLATOR methods all the synonim columns are exchanged with our columns * Done in place, in order to 1)ProjSchemaCreator.chooseProjections does not * work with synonims, which simplifies the function 2)avoid doing it * multiple times (getType and getStringExpr usually follow indexOf) */ private void translateExpr(TupleSchema tupleSchema, Expression expr) { final List<Column> columns = ParserUtil.getJSQLColumns(expr); for (final Column column : columns) { final String originalColumnStr = tupleSchema.getOriginal(column); if (originalColumnStr != null) ParserUtil.copyColumn(column, originalColumnStr); } } // Commented out when List<ColumnTypeNames> moved to TupleSchema. // Not needed anyway because of the single-last-node API requirement. // If decided to push forward, translation akin to one from contains method // might be needed. // /* // * Is component already hashed by hashIndexes // * (does its parent sends tuples hashed by hashIndexes). // * hashIndexes are indexes wrt component. // * // * If returns true not only if hashes are equivalent, but also if the // parent groups tuples exactly the same as the affected component, // * with addition of some more columns. This means that Join and // Aggregation can be performed on the same node. // * Inspiration taken from the Nephele paper. // * // */ // public boolean isHashedBy(Component component, List<Integer> hashIndexes, // Map<String, CostParams> compCost) { // //schema of hashIndexes in component // List<ColumnNameType> tupleSchema = // compCost.get(component.getName()).getSchema(); // List<ColumnNameType> projectedTupleSchema = // ParserUtil.getProjectedSchema(tupleSchema, hashIndexes); // // Component[] parents = component.getParents(); // if(parents!=null){ // //if both parents have only hashIndexes, they point to the same indexes // in the child // //so we choose arbitrarily first parent // Component parent = parents[0]; // List<Integer> parentHashes = parent.getHashIndexes(); // if(parent.getHashExpressions() == null){ // List<ColumnNameType> parentTupleSchema = // compCost.get(parent.getName()).getSchema(); // List<ColumnNameType> projectedParentTupleSchema = // ParserUtil.getProjectedSchema(parentTupleSchema, parentHashes); // return isSuperset(projectedParentTupleSchema, projectedTupleSchema); // } // } // return false; // } // // private boolean isSuperset(List<ColumnNameType> parentHashSchema, // List<ColumnNameType> hashSchema) { // int parentSize = parentHashSchema.size(); // int affectedSize = hashSchema.size(); // // if (parentSize < affectedSize){ // return false; // }else if(parentSize == affectedSize){ // return parentHashSchema.equals(hashSchema); // }else{ // //parent partitions more than necessary for a child // for(int i=0; i<affectedSize; i++){ // if (!(hashSchema.get(i).equals(parentHashSchema.get(i)))){ // return false; // } // } // return true; // } // } }