Package net.hydromatic.optiq.materialize

Source Code of net.hydromatic.optiq.materialize.MaterializationService

/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde 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 net.hydromatic.avatica.ColumnMetaData;

import net.hydromatic.linq4j.*;
import net.hydromatic.linq4j.expressions.Expression;
import net.hydromatic.linq4j.function.Function1;
import net.hydromatic.linq4j.function.Functions;

import net.hydromatic.optiq.*;
import net.hydromatic.optiq.impl.clone.CloneSchema;
import net.hydromatic.optiq.impl.java.JavaTypeFactory;
import net.hydromatic.optiq.jdbc.*;
import net.hydromatic.optiq.prepare.Prepare;

import org.eigenbase.reltype.RelDataType;
import org.eigenbase.reltype.RelDataTypeImpl;
import org.eigenbase.util.Pair;

import java.lang.reflect.Type;
import java.util.*;

/**
* Manages the collection of materialized tables known to the system,
* and the process by which they become valid and invalid.
*/
public class MaterializationService {
  private static final MaterializationService INSTANCE =
      new MaterializationService();

  /** For testing. */
  private static final ThreadLocal<MaterializationService> THREAD_INSTANCE =
      new ThreadLocal<MaterializationService>() {
        @Override
        protected MaterializationService initialValue() {
          return new MaterializationService();
        }
      };

  private final MaterializationActor actor = new MaterializationActor();

  private MaterializationService() {
  }

  /** Defines a new materialization. Returns its key. */
  public MaterializationKey defineMaterialization(final OptiqSchema schema,
      String viewSql, List<String> viewSchemaPath, String tableName) {
    final OptiqConnection connection =
        MetaImpl.connect(schema.root(), null);
    final MaterializationKey key = new MaterializationKey();
    Table materializedTable;
    RelDataType rowType = null;
    OptiqSchema.TableEntry tableEntry;
    if (tableName != null) {
      final Pair<String, Table> pair = schema.getTable(tableName, true);
      materializedTable = pair == null ? null : pair.right;
      if (materializedTable == null) {
        final OptiqPrepare.PrepareResult<Object> prepareResult =
            Schemas.prepare(connection, schema, viewSchemaPath, viewSql);
        rowType = prepareResult.rowType;
        final JavaTypeFactory typeFactory = connection.getTypeFactory();
        materializedTable =
            CloneSchema.createCloneTable(typeFactory,
                RelDataTypeImpl.proto(prepareResult.rowType),
                Functions.adapt(prepareResult.structType.columns,
                    new Function1<ColumnMetaData, ColumnMetaData.Rep>() {
                      public ColumnMetaData.Rep apply(ColumnMetaData column) {
                        return column.type.representation;
                      }
                    }),
                new AbstractQueryable<Object>() {
                  public Enumerator<Object> enumerator() {
                    final DataContext dataContext =
                        Schemas.createDataContext(connection);
                    return prepareResult.enumerator(dataContext);
                  }

                  public Type getElementType() {
                    return Object.class;
                  }

                  public Expression getExpression() {
                    throw new UnsupportedOperationException();
                  }

                  public QueryProvider getProvider() {
                    return connection;
                  }

                  public Iterator<Object> iterator() {
                    final DataContext dataContext =
                        Schemas.createDataContext(connection);
                    return prepareResult.iterator(dataContext);
                  }
                });
        schema.add(tableName, materializedTable);
      }
      tableEntry = schema.add(tableName, materializedTable);
    } else {
      tableEntry = null;
    }
    if (rowType == null) {
      // If we didn't validate the SQL by populating a table, validate it now.
      final OptiqPrepare.ParseResult parse =
          Schemas.parse(connection, schema, viewSchemaPath, viewSql);
      rowType = parse.rowType;
    }
    final MaterializationActor.Materialization materialization =
        new MaterializationActor.Materialization(key, schema.root(),
            tableEntry, viewSql, rowType);
    actor.keyMap.put(materialization.key, materialization);
    return key;
  }

  /** Checks whether a materialization is valid, and if so, returns the table
   * where the data are stored. */
  public OptiqSchema.TableEntry checkValid(MaterializationKey key) {
    final MaterializationActor.Materialization materialization =
        actor.keyMap.get(key);
    if (materialization != null) {
      return materialization.materializedTable;
    }
    return null;
  }

  /** Gathers a list of all materialized tables known within a given root
   * schema. (Each root schema defines a disconnected namespace, with no overlap
   * with the current schema. Especially in a test run, the contents of two
   * root schemas may look similar.) */
  public List<Prepare.Materialization> query(OptiqSchema rootSchema) {
    final List<Prepare.Materialization> list =
        new ArrayList<Prepare.Materialization>();
    for (MaterializationActor.Materialization materialization
        : actor.keyMap.values()) {
      if (materialization.rootSchema == rootSchema
          && materialization.materializedTable != null) {
        list.add(
            new Prepare.Materialization(materialization.materializedTable,
                materialization.sql));
      }
    }
    return list;
  }

  /** De-registers all materialized tables in the system. */
  public void clear() {
    actor.keyMap.clear();
  }

  /** Used by tests, to ensure that they see their own service. */
  public static void setThreadLocal() {
    THREAD_INSTANCE.set(new MaterializationService());
  }

  /** Returns the instance of the materialization service. Usually the global
   * one, but returns a thread-local one during testing (when
   * {@link #setThreadLocal()} has been called by the current thread). */
  public static MaterializationService instance() {
    MaterializationService materializationService = THREAD_INSTANCE.get();
    if (materializationService != null) {
      return materializationService;
    }
    return INSTANCE;
  }

}

// End MaterializationService.java
TOP

Related Classes of net.hydromatic.optiq.materialize.MaterializationService

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.