Package net.hydromatic.optiq.prepare

Source Code of net.hydromatic.optiq.prepare.OptiqMaterializer$RelNullShuttle

/*
// 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.prepare;

import net.hydromatic.optiq.*;
import net.hydromatic.optiq.impl.StarTable;
import net.hydromatic.optiq.jdbc.OptiqPrepare;
import net.hydromatic.optiq.jdbc.OptiqSchema;
import net.hydromatic.optiq.rules.java.EnumerableConvention;
import net.hydromatic.optiq.rules.java.EnumerableRel;

import org.eigenbase.rel.*;
import org.eigenbase.relopt.*;
import org.eigenbase.sql.SqlNode;
import org.eigenbase.sql.parser.SqlParseException;
import org.eigenbase.sql.parser.SqlParser;
import org.eigenbase.sql2rel.SqlToRelConverter;

import java.util.*;

/**
* Context for populating a {@link Materialization}.
*/
class OptiqMaterializer extends OptiqPrepareImpl.OptiqPreparingStmt {
  public OptiqMaterializer(OptiqPrepare.Context context,
      CatalogReader catalogReader, OptiqSchema schema,
      RelOptPlanner planner) {
    super(context, catalogReader, catalogReader.getTypeFactory(), schema,
        EnumerableRel.Prefer.ANY, planner, EnumerableConvention.INSTANCE);
  }

  /** Populates a materialization record, converting a table path
   * (essentially a list of strings, like ["hr", "sales"]) into a table object
   * that can be used in the planning process. */
  void populate(Materialization materialization) {
    SqlParser parser = SqlParser.create(materialization.sql);
    SqlNode node;
    try {
      node = parser.parseStmt();
    } catch (SqlParseException e) {
      throw new RuntimeException("parse failed", e);
    }

    SqlToRelConverter sqlToRelConverter2 =
        getSqlToRelConverter(getSqlValidator(), catalogReader);

    materialization.queryRel =
        sqlToRelConverter2.convertQuery(node, true, true);

    // Identify and substitute a StarTable in queryRel.
    //
    // It is possible that no StarTables match. That is OK, but the
    // materialization patterns that are recognized will not be as rich.
    //
    // It is possible that more than one StarTable matches. TBD: should we
    // take the best (whatever that means), or all of them?
    useStar(schema, materialization);

    RelOptTable table =
        this.catalogReader.getTable(materialization.materializedTable.path());
    materialization.tableRel = sqlToRelConverter2.toRel(table);
  }

  /** Converts a relational expression to use a
   * {@link net.hydromatic.optiq.impl.StarTable} defined in {@code schema}.
   * Uses the first star table that fits. */
  private void useStar(OptiqSchema schema, Materialization materialization) {
    List<OptiqSchema.TableEntry> starTables = getStarTables(schema);
    if (starTables.isEmpty()) {
      // Don't waste effort converting to leaf-join form.
      return;
    }
    final RelNode rel2 =
        RelOptMaterialization.toLeafJoinForm(materialization.queryRel);
    for (OptiqSchema.TableEntry starTable : starTables) {
      final Table table = starTable.getTable();
      assert table instanceof StarTable;
      RelOptTableImpl starRelOptTable =
          RelOptTableImpl.create(catalogReader, table.getRowType(typeFactory),
              starTable);
      final RelNode rel3 =
          RelOptMaterialization.tryUseStar(rel2, starRelOptTable);
      if (rel3 != null) {
        // Success -- we found a star table that matches.
        materialization.materialize(rel3, starRelOptTable);
        System.out.println("Materialization "
            + materialization.materializedTable + " matched star table "
            + starTable + "; query after re-write: "
            + RelOptUtil.toString(materialization.queryRel));
        return;
      }
    }
  }

  /** Returns the star tables defined in a schema.
   * @param schema Schema */
  private List<OptiqSchema.TableEntry> getStarTables(OptiqSchema schema) {
    final List<OptiqSchema.TableEntry> list =
        new ArrayList<OptiqSchema.TableEntry>();
    // TODO: Assumes that star tables are all defined in a schema called
    // "mat". Instead, we should look for star tables that use a given set of
    // tables, regardless of schema.
    final OptiqSchema matSchema = schema.root().getSubSchema("mat", true);
    if (matSchema != null) {
      for (OptiqSchema.TableEntry tis : matSchema.tableMap.values()) {
        if (tis.getTable().getJdbcTableType() == Schema.TableType.STAR) {
          list.add(tis);
        }
      }
    }
    return list;
  }

  /** Implementation of {@link RelShuttle} that returns each relational
   * expression unchanged. It does not visit children. */
  static class RelNullShuttle implements RelShuttle {
    public RelNode visit(TableAccessRelBase scan) {
      return scan;
    }
    public RelNode visit(TableFunctionRelBase scan) {
      return scan;
    }
    public RelNode visit(ValuesRel values) {
      return values;
    }
    public RelNode visit(FilterRel filter) {
      return filter;
    }
    public RelNode visit(ProjectRel project) {
      return project;
    }
    public RelNode visit(JoinRel join) {
      return join;
    }
    public RelNode visit(CorrelatorRel correlator) {
      return correlator;
    }
    public RelNode visit(UnionRel union) {
      return union;
    }
    public RelNode visit(IntersectRel intersect) {
      return intersect;
    }
    public RelNode visit(MinusRel minus) {
      return minus;
    }
    public RelNode visit(AggregateRel aggregate) {
      return aggregate;
    }
    public RelNode visit(SortRel sort) {
      return sort;
    }
    public RelNode visit(RelNode other) {
      return other;
    }
  }

}

// End OptiqMaterializer.java
TOP

Related Classes of net.hydromatic.optiq.prepare.OptiqMaterializer$RelNullShuttle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.