/* * 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.impl.tpcds; import net.hydromatic.linq4j.Enumerator; import net.hydromatic.linq4j.Linq4j; import net.hydromatic.linq4j.QueryProvider; import net.hydromatic.linq4j.Queryable; import net.hydromatic.optiq.SchemaPlus; import net.hydromatic.optiq.Statistic; import net.hydromatic.optiq.Statistics; import net.hydromatic.optiq.Table; import net.hydromatic.optiq.impl.AbstractSchema; import net.hydromatic.optiq.impl.AbstractTableQueryable; import net.hydromatic.optiq.impl.java.AbstractQueryableTable; import org.eigenbase.reltype.RelDataType; import org.eigenbase.reltype.RelDataTypeFactory; import org.eigenbase.util.Bug; import com.google.common.collect.ImmutableMap; import java.sql.Date; import java.util.BitSet; import java.util.Collections; import java.util.List; import java.util.Map; import net.hydromatic.tpcds.TpcdsColumn; import net.hydromatic.tpcds.TpcdsEntity; import net.hydromatic.tpcds.TpcdsTable; /** Schema that provides TPC-DS tables, populated according to a * particular scale factor. */ public class TpcdsSchema extends AbstractSchema { private final double scaleFactor; private final int part; private final int partCount; private final ImmutableMap<String, Table> tableMap; // From TPC-DS spec, table 3-2 "Database Row Counts", for 1G sizing. private static final ImmutableMap<String, Integer> TABLE_ROW_COUNTS = ImmutableMap.<String, Integer>builder() .put("call_center", 8) .put("catalog_page", 11718) .put("catalog_returns", 144067) .put("catalog_sales", 1441548) .put("customer", 100000) .put("customer_address", 50000) .put("customer_demographics", 1920800) .put("date_dim", 73049) .put("household_demographics", 7200) .put("income_band", 20) .put("inventory", 11745000) .put("item", 18000) .put("promotion", 300) .put("reason", 35) .put("ship_mode", 20) .put("store", 12) .put("store_returns", 287514) .put("store_sales", 2880404) .put("time_dim", 86400) .put("warehouse", 5) .put("web_page", 60) .put("web_returns", 71763) .put("web_sales", 719384) .put("web_site", 1) .build(); public TpcdsSchema(double scaleFactor, int part, int partCount) { this.scaleFactor = scaleFactor; this.part = part; this.partCount = partCount; final ImmutableMap.Builder<String, Table> builder = ImmutableMap.builder(); for (TpcdsTable<?> tpcdsTable : TpcdsTable.getTables()) { //noinspection unchecked builder.put(tpcdsTable.getTableName().toUpperCase(), new TpcdsQueryableTable(tpcdsTable)); } this.tableMap = builder.build(); } @Override protected Map<String, Table> getTableMap() { return tableMap; } /** Definition of a table in the TPC-DS schema. */ private class TpcdsQueryableTable<E extends TpcdsEntity> extends AbstractQueryableTable { private final TpcdsTable<E> tpcdsTable; TpcdsQueryableTable(TpcdsTable<E> tpcdsTable) { super(Object[].class); this.tpcdsTable = tpcdsTable; } @Override public Statistic getStatistic() { Bug.upgrade("add row count estimate to TpcdsTable, and use it"); Integer rowCount = TABLE_ROW_COUNTS.get(tpcdsTable.name); assert rowCount != null : tpcdsTable.name; return Statistics.of(rowCount, Collections.<BitSet>emptyList()); } public <T> Queryable<T> asQueryable(final QueryProvider queryProvider, final SchemaPlus schema, final String tableName) { //noinspection unchecked return (Queryable) new AbstractTableQueryable<Object[]>(queryProvider, schema, this, tableName) { public Enumerator<Object[]> enumerator() { final Enumerator<E> iterator = Linq4j.iterableEnumerator( tpcdsTable.createGenerator(scaleFactor, part, partCount)); return new Enumerator<Object[]>() { public Object[] current() { final List<TpcdsColumn<E>> columns = tpcdsTable.getColumns(); final Object[] objects = new Object[columns.size()]; int i = 0; for (TpcdsColumn<E> column : columns) { objects[i++] = value(column, iterator.current()); } return objects; } private Object value(TpcdsColumn<E> tpcdsColumn, E current) { final Class<?> type = realType(tpcdsColumn); if (type == String.class) { return tpcdsColumn.getString(current); } else if (type == Double.class) { return tpcdsColumn.getDouble(current); } else if (type == Date.class) { return Date.valueOf(tpcdsColumn.getString(current)); } else { return tpcdsColumn.getLong(current); } } public boolean moveNext() { return iterator.moveNext(); } public void reset() { iterator.reset(); } public void close() { } }; } }; } public RelDataType getRowType(RelDataTypeFactory typeFactory) { final RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder(); for (TpcdsColumn<E> column : tpcdsTable.getColumns()) { builder.add(column.getColumnName().toUpperCase(), typeFactory.createJavaType(realType(column))); } return builder.build(); } private Class<?> realType(TpcdsColumn<E> column) { if (column.getColumnName().endsWith("date")) { return Date.class; } return column.getType(); } } } // End TpcdsSchema.java