/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to you 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 net.hydromatic.optiq.materialize; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.pentaho.aggdes.algorithm.Algorithm; import org.pentaho.aggdes.algorithm.Progress; import org.pentaho.aggdes.algorithm.Result; import org.pentaho.aggdes.algorithm.impl.MonteCarloAlgorithm; import org.pentaho.aggdes.algorithm.util.ArgumentUtils; import org.pentaho.aggdes.model.Aggregate; import org.pentaho.aggdes.model.Attribute; import org.pentaho.aggdes.model.Dialect; import org.pentaho.aggdes.model.Dimension; import org.pentaho.aggdes.model.Measure; import org.pentaho.aggdes.model.Parameter; import org.pentaho.aggdes.model.Schema; import org.pentaho.aggdes.model.StatisticsProvider; import org.pentaho.aggdes.model.Table; import java.io.PrintWriter; import java.util.List; /** * Algorithm that suggests a set of initial tiles (materialized aggregate views) * for a given lattice. */ public class TileSuggester { private static final Function<Attribute, Lattice.Column> TO_COLUMN = new Function<Attribute, Lattice.Column>() { public Lattice.Column apply(Attribute input) { return ((AttributeImpl) input).column; } }; private final Lattice lattice; public TileSuggester(Lattice lattice) { this.lattice = lattice; } public Iterable<? extends Lattice.Tile> tiles() { final Algorithm algorithm = new MonteCarloAlgorithm(); final PrintWriter pw = new PrintWriter(System.out); final Progress progress = new ArgumentUtils.TextProgress(pw); final StatisticsProvider statisticsProvider = new StatisticsProviderImpl(lattice); final double f = statisticsProvider.getFactRowCount(); final ImmutableMap<Parameter, Object> map = ImmutableMap.<Parameter, Object>of( Algorithm.ParameterEnum.timeLimitSeconds, 1, Algorithm.ParameterEnum.aggregateLimit, 3, Algorithm.ParameterEnum.costLimit, f * 5d); final SchemaImpl schema = new SchemaImpl(lattice, statisticsProvider); final Result result = algorithm.run(schema, map, progress); final ImmutableList.Builder<Lattice.Tile> tiles = ImmutableList.builder(); for (Aggregate aggregate : result.getAggregates()) { System.out.println(aggregate); tiles.add(toTile(aggregate)); } return tiles.build(); } private Lattice.Tile toTile(Aggregate aggregate) { final Lattice.TileBuilder tileBuilder = new Lattice.TileBuilder(); for (Lattice.Measure measure : lattice.defaultMeasures) { tileBuilder.addMeasure(measure); } for (Attribute attribute : aggregate.getAttributes()) { tileBuilder.addDimension(((AttributeImpl) attribute).column); } return tileBuilder.build(); } /** Implementation of {@link Schema} based on a {@link Lattice}. */ private static class SchemaImpl implements Schema { private final StatisticsProvider statisticsProvider; private final TableImpl table; private final ImmutableList<AttributeImpl> attributes; public SchemaImpl(Lattice lattice, StatisticsProvider statisticsProvider) { this.statisticsProvider = statisticsProvider; this.table = new TableImpl(); final ImmutableList.Builder<AttributeImpl> attributeBuilder = ImmutableList.builder(); for (Lattice.Column column : lattice.columns) { attributeBuilder.add(new AttributeImpl(column, table)); } this.attributes = attributeBuilder.build(); } public List<? extends Table> getTables() { return ImmutableList.of(table); } public List<Measure> getMeasures() { throw new UnsupportedOperationException(); } public List<? extends Dimension> getDimensions() { throw new UnsupportedOperationException(); } public List<? extends Attribute> getAttributes() { return attributes; } public StatisticsProvider getStatisticsProvider() { return statisticsProvider; } public Dialect getDialect() { throw new UnsupportedOperationException(); } public String generateAggregateSql(Aggregate aggregate, List<String> columnNameList) { throw new UnsupportedOperationException(); } } /** Implementation of {@link Table} based on a {@link Lattice}. * There is only one table (in this sense of table) in a lattice. * The algorithm does not really care about tables. */ private static class TableImpl implements Table { public String getLabel() { return "TABLE"; } public Table getParent() { return null; } } /** Implementation of {@link Attribute} based on a {@link Lattice.Column}. */ private static class AttributeImpl implements Attribute { private final Lattice.Column column; private final TableImpl table; private AttributeImpl(Lattice.Column column, TableImpl table) { this.column = column; this.table = table; } @Override public String toString() { return getLabel(); } public String getLabel() { return column.alias; } public Table getTable() { return table; } public double estimateSpace() { return 0; } public String getCandidateColumnName() { return null; } public String getDatatype(Dialect dialect) { return null; } public List<Attribute> getAncestorAttributes() { return ImmutableList.of(); } } /** Implementation of {@link org.pentaho.aggdes.model.StatisticsProvider} * that asks the lattice. */ private static class StatisticsProviderImpl implements StatisticsProvider { private final Lattice lattice; public StatisticsProviderImpl(Lattice lattice) { this.lattice = lattice; } public double getFactRowCount() { return lattice.getFactRowCount(); } public double getRowCount(List<Attribute> attributes) { return lattice.getRowCount(Lists.transform(attributes, TO_COLUMN)); } public double getSpace(List<Attribute> attributes) { return attributes.size(); } public double getLoadTime(List<Attribute> attributes) { return getSpace(attributes) * getRowCount(attributes); } } } // End TileSuggester.java