All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.shaded.org.apache.calcite.prepare.RelOptTableImpl Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * 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 com.hazelcast.shaded.org.apache.calcite.prepare;

import com.hazelcast.shaded.org.apache.calcite.jdbc.CalciteSchema;
import com.hazelcast.shaded.org.apache.calcite.linq4j.tree.Expression;
import com.hazelcast.shaded.org.apache.calcite.linq4j.tree.TableExpressionFactory;
import com.hazelcast.shaded.org.apache.calcite.materialize.Lattice;
import com.hazelcast.shaded.org.apache.calcite.plan.RelOptSchema;
import com.hazelcast.shaded.org.apache.calcite.plan.RelOptTable;
import com.hazelcast.shaded.org.apache.calcite.rel.RelCollation;
import com.hazelcast.shaded.org.apache.calcite.rel.RelDistribution;
import com.hazelcast.shaded.org.apache.calcite.rel.RelDistributionTraitDef;
import com.hazelcast.shaded.org.apache.calcite.rel.RelFieldCollation;
import com.hazelcast.shaded.org.apache.calcite.rel.RelNode;
import com.hazelcast.shaded.org.apache.calcite.rel.RelReferentialConstraint;
import com.hazelcast.shaded.org.apache.calcite.rel.logical.LogicalTableScan;
import com.hazelcast.shaded.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.shaded.org.apache.calcite.rel.type.RelDataTypeFactory;
import com.hazelcast.shaded.org.apache.calcite.rel.type.RelDataTypeField;
import com.hazelcast.shaded.org.apache.calcite.rel.type.RelProtoDataType;
import com.hazelcast.shaded.org.apache.calcite.rel.type.RelRecordType;
import com.hazelcast.shaded.org.apache.calcite.schema.ColumnStrategy;
import com.hazelcast.shaded.org.apache.calcite.schema.ModifiableTable;
import com.hazelcast.shaded.org.apache.calcite.schema.Path;
import com.hazelcast.shaded.org.apache.calcite.schema.ScannableTable;
import com.hazelcast.shaded.org.apache.calcite.schema.Schema;
import com.hazelcast.shaded.org.apache.calcite.schema.SchemaPlus;
import com.hazelcast.shaded.org.apache.calcite.schema.SchemaVersion;
import com.hazelcast.shaded.org.apache.calcite.schema.Schemas;
import com.hazelcast.shaded.org.apache.calcite.schema.StreamableTable;
import com.hazelcast.shaded.org.apache.calcite.schema.Table;
import com.hazelcast.shaded.org.apache.calcite.schema.TemporalTable;
import com.hazelcast.shaded.org.apache.calcite.schema.TranslatableTable;
import com.hazelcast.shaded.org.apache.calcite.schema.Wrapper;
import com.hazelcast.shaded.org.apache.calcite.sql.SqlAccessType;
import com.hazelcast.shaded.org.apache.calcite.sql.validate.SqlModality;
import com.hazelcast.shaded.org.apache.calcite.sql.validate.SqlMonotonicity;
import com.hazelcast.shaded.org.apache.calcite.sql2rel.InitializerExpressionFactory;
import com.hazelcast.shaded.org.apache.calcite.sql2rel.NullInitializerExpressionFactory;
import com.hazelcast.shaded.org.apache.calcite.util.ImmutableBitSet;
import com.hazelcast.shaded.org.apache.calcite.util.Pair;
import com.hazelcast.shaded.org.apache.calcite.util.Util;

import com.hazelcast.shaded.com.google.common.collect.ImmutableList;

import com.hazelcast.shaded.org.checkerframework.checker.nullness.qual.Nullable;

import java.util.AbstractList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static java.util.Objects.requireNonNull;

/**
 * Implementation of {@link com.hazelcast.shaded.org.apache.calcite.plan.RelOptTable}.
 */
public class RelOptTableImpl extends Prepare.AbstractPreparingTable {
  private final @Nullable RelOptSchema schema;
  private final RelDataType rowType;
  private final @Nullable Table table;
  private final @Nullable TableExpressionFactory tableExpressionFactory;
  private final ImmutableList names;

  /** Estimate for the row count, or null.
   *
   * 

If not null, overrides the estimate from the actual table. * *

Useful when a table that contains a materialized query result is being * used to replace a query expression that wildly underestimates the row * count. Now the materialized table can tell the same lie. */ private final @Nullable Double rowCount; private RelOptTableImpl( @Nullable RelOptSchema schema, RelDataType rowType, List names, @Nullable Table table, @Nullable TableExpressionFactory tableExpressionFactory, @Nullable Double rowCount) { this.schema = schema; this.rowType = requireNonNull(rowType, "rowType"); this.names = ImmutableList.copyOf(names); this.table = table; // may be null this.tableExpressionFactory = tableExpressionFactory; // may be null this.rowCount = rowCount; // may be null } public static RelOptTableImpl create( @Nullable RelOptSchema schema, RelDataType rowType, List names, Expression expression) { return new RelOptTableImpl(schema, rowType, names, null, c -> expression, null); } @Deprecated // to be removed before 2.0 public static RelOptTableImpl create( @Nullable RelOptSchema schema, RelDataType rowType, List names, Table table, Expression expression) { return create(schema, rowType, names, table, c -> expression); } /** * Creates {@link RelOptTableImpl} instance with specified arguments * and row count obtained from table statistic. * * @param schema table schema * @param rowType table row type * @param names full table path * @param table table * @param expressionFactory expression function for accessing table data * in the generated code * * @return {@link RelOptTableImpl} instance */ public static RelOptTableImpl create( @Nullable RelOptSchema schema, RelDataType rowType, List names, Table table, TableExpressionFactory expressionFactory) { return new RelOptTableImpl(schema, rowType, names, table, expressionFactory, table.getStatistic().getRowCount()); } public static RelOptTableImpl create(@Nullable RelOptSchema schema, RelDataType rowType, Table table, Path path) { final SchemaPlus schemaPlus = MySchemaPlus.create(path); return new RelOptTableImpl(schema, rowType, Pair.left(path), table, c -> Schemas.getTableExpression(schemaPlus, Util.last(path).left, table, c), table.getStatistic().getRowCount()); } public static RelOptTableImpl create(@Nullable RelOptSchema schema, RelDataType rowType, final CalciteSchema.TableEntry tableEntry, @Nullable Double rowCount) { final Table table = tableEntry.getTable(); return new RelOptTableImpl(schema, rowType, tableEntry.path(), table, c -> Schemas.getTableExpression(tableEntry.schema.plus(), tableEntry.name, table, c), rowCount); } /** * Creates a copy of this RelOptTable. The new RelOptTable will have newRowType. */ public RelOptTableImpl copy(RelDataType newRowType) { return new RelOptTableImpl(this.schema, newRowType, this.names, this.table, this.tableExpressionFactory, this.rowCount); } @Override public String toString() { return "RelOptTableImpl{" + "schema=" + schema + ", names= " + names + ", table=" + table + ", rowType=" + rowType + '}'; } public static RelOptTableImpl create(@Nullable RelOptSchema schema, RelDataType rowType, Table table, ImmutableList names) { assert table instanceof TranslatableTable || table instanceof ScannableTable || table instanceof ModifiableTable; return new RelOptTableImpl(schema, rowType, names, table, null, null); } @Override public @Nullable T unwrap(Class clazz) { if (clazz.isInstance(this)) { return clazz.cast(this); } if (clazz.isInstance(table)) { return clazz.cast(table); } if (table instanceof Wrapper) { final T t = ((Wrapper) table).unwrap(clazz); if (t != null) { return t; } } if (clazz == CalciteSchema.class && schema != null) { return clazz.cast( Schemas.subSchema(((CalciteCatalogReader) schema).rootSchema, Util.skipLast(getQualifiedName()))); } return null; } @Override public @Nullable Expression getExpression(Class clazz) { if (tableExpressionFactory == null) { return null; } return tableExpressionFactory.create(clazz); } @Override protected RelOptTable extend(Table extendedTable) { RelOptSchema schema = requireNonNull(getRelOptSchema(), "relOptSchema"); final RelDataType extendedRowType = extendedTable.getRowType(schema.getTypeFactory()); return new RelOptTableImpl(schema, extendedRowType, getQualifiedName(), extendedTable, tableExpressionFactory, getRowCount()); } @Override public boolean equals(@Nullable Object obj) { return obj instanceof RelOptTableImpl && this.rowType.equals(((RelOptTableImpl) obj).getRowType()) && this.table == ((RelOptTableImpl) obj).table; } @Override public int hashCode() { return (this.table == null) ? super.hashCode() : this.table.hashCode(); } @Override public double getRowCount() { if (rowCount != null) { return rowCount; } if (table != null) { final Double rowCount = table.getStatistic().getRowCount(); if (rowCount != null) { return rowCount; } } return 100d; } @Override public @Nullable RelOptSchema getRelOptSchema() { return schema; } @Override public RelNode toRel(ToRelContext context) { // Make sure rowType's list is immutable. If rowType is DynamicRecordType, creates a new // RelOptTable by replacing with immutable RelRecordType using the same field list. if (this.getRowType().isDynamicStruct()) { final RelDataType staticRowType = new RelRecordType(getRowType().getFieldList()); final RelOptTable relOptTable = this.copy(staticRowType); return relOptTable.toRel(context); } // If there are any virtual columns, create a copy of this table without // those virtual columns. final List strategies = getColumnStrategies(); if (strategies.contains(ColumnStrategy.VIRTUAL)) { final RelDataTypeFactory.Builder b = context.getCluster().getTypeFactory().builder(); for (RelDataTypeField field : rowType.getFieldList()) { if (strategies.get(field.getIndex()) != ColumnStrategy.VIRTUAL) { b.add(field.getName(), field.getType()); } } final RelOptTable relOptTable = new RelOptTableImpl(this.schema, b.build(), this.names, this.table, this.tableExpressionFactory, this.rowCount) { @Override public @Nullable T unwrap(Class clazz) { if (clazz.isAssignableFrom(InitializerExpressionFactory.class)) { return clazz.cast(NullInitializerExpressionFactory.INSTANCE); } return super.unwrap(clazz); } }; return relOptTable.toRel(context); } if (table instanceof TranslatableTable) { return ((TranslatableTable) table).toRel(context, this); } return LogicalTableScan.create(context.getCluster(), this, context.getTableHints()); } @Override public @Nullable List getCollationList() { if (table != null) { return table.getStatistic().getCollations(); } return ImmutableList.of(); } @Override public @Nullable RelDistribution getDistribution() { if (table != null) { return table.getStatistic().getDistribution(); } return RelDistributionTraitDef.INSTANCE.getDefault(); } @Override public boolean isKey(ImmutableBitSet columns) { if (table != null) { return table.getStatistic().isKey(columns); } return false; } @Override public @Nullable List getKeys() { if (table != null) { return table.getStatistic().getKeys(); } return ImmutableList.of(); } @Override public @Nullable List getReferentialConstraints() { if (table != null) { return table.getStatistic().getReferentialConstraints(); } return ImmutableList.of(); } @Override public RelDataType getRowType() { return rowType; } @Override public boolean supportsModality(SqlModality modality) { switch (modality) { case STREAM: return table instanceof StreamableTable; default: return !(table instanceof StreamableTable); } } @Override public boolean isTemporal() { return table instanceof TemporalTable; } @Override public List getQualifiedName() { return names; } @Override public SqlMonotonicity getMonotonicity(String columnName) { if (table == null) { return SqlMonotonicity.NOT_MONOTONIC; } List collations = table.getStatistic().getCollations(); if (collations == null) { return SqlMonotonicity.NOT_MONOTONIC; } for (RelCollation collation : collations) { final RelFieldCollation fieldCollation = collation.getFieldCollations().get(0); final int fieldIndex = fieldCollation.getFieldIndex(); if (fieldIndex < rowType.getFieldCount() && rowType.getFieldNames().get(fieldIndex).equals(columnName)) { return fieldCollation.direction.monotonicity(); } } return SqlMonotonicity.NOT_MONOTONIC; } @Override public SqlAccessType getAllowedAccess() { return SqlAccessType.ALL; } /** Helper for {@link #getColumnStrategies()}. */ public static List columnStrategies(final RelOptTable table) { final int fieldCount = table.getRowType().getFieldCount(); final InitializerExpressionFactory ief = Util.first(table.unwrap(InitializerExpressionFactory.class), NullInitializerExpressionFactory.INSTANCE); return new AbstractList() { @Override public int size() { return fieldCount; } @Override public ColumnStrategy get(int index) { return ief.generationStrategy(table, index); } }; } /** Converts the ordinal of a field into the ordinal of a stored field. * That is, it subtracts the number of virtual fields that come before it. */ public static int realOrdinal(final RelOptTable table, int i) { List strategies = table.getColumnStrategies(); int n = 0; for (int j = 0; j < i; j++) { switch (strategies.get(j)) { case VIRTUAL: ++n; break; default: break; } } return i - n; } /** Returns the row type of a table after any {@link ColumnStrategy#VIRTUAL} * columns have been removed. This is the type of the records that are * actually stored. */ public static RelDataType realRowType(RelOptTable table) { final RelDataType rowType = table.getRowType(); final List strategies = columnStrategies(table); if (!strategies.contains(ColumnStrategy.VIRTUAL)) { return rowType; } final RelDataTypeFactory.Builder builder = requireNonNull(table.getRelOptSchema(), () -> "relOptSchema for table " + table).getTypeFactory().builder(); for (RelDataTypeField field : rowType.getFieldList()) { if (strategies.get(field.getIndex()) != ColumnStrategy.VIRTUAL) { builder.add(field); } } return builder.build(); } /** Implementation of {@link SchemaPlus} that wraps a regular schema and knows * its name and parent. * *

It is read-only, and functionality is limited in other ways, it but * allows table expressions to be generated. */ private static class MySchemaPlus implements SchemaPlus { private final @Nullable SchemaPlus parent; private final String name; private final Schema schema; MySchemaPlus(@Nullable SchemaPlus parent, String name, Schema schema) { this.parent = parent; this.name = name; this.schema = schema; } public static MySchemaPlus create(Path path) { final Pair pair = Util.last(path); final SchemaPlus parent; if (path.size() == 1) { parent = null; } else { parent = create(path.parent()); } return new MySchemaPlus(parent, pair.left, pair.right); } @Override public @Nullable SchemaPlus getParentSchema() { return parent; } @Override public String getName() { return name; } @Override public @Nullable SchemaPlus getSubSchema(String name) { final Schema subSchema = schema.getSubSchema(name); return subSchema == null ? null : new MySchemaPlus(this, name, subSchema); } @Override public SchemaPlus add(String name, Schema schema) { throw new UnsupportedOperationException(); } @Override public void add(String name, Table table) { throw new UnsupportedOperationException(); } @Override public boolean removeTable(String name) { throw new UnsupportedOperationException(); } @Override public void add(String name, com.hazelcast.shaded.org.apache.calcite.schema.Function function) { throw new UnsupportedOperationException(); } @Override public void add(String name, RelProtoDataType type) { throw new UnsupportedOperationException(); } @Override public void add(String name, Lattice lattice) { throw new UnsupportedOperationException(); } @Override public boolean isMutable() { return schema.isMutable(); } @Override public @Nullable T unwrap(Class clazz) { return null; } @Override public void setPath(ImmutableList> path) { throw new UnsupportedOperationException(); } @Override public void setCacheEnabled(boolean cache) { throw new UnsupportedOperationException(); } @Override public boolean isCacheEnabled() { return false; } @Override public @Nullable Table getTable(String name) { return schema.getTable(name); } @Override public Set getTableNames() { return schema.getTableNames(); } @Override public @Nullable RelProtoDataType getType(String name) { return schema.getType(name); } @Override public Set getTypeNames() { return schema.getTypeNames(); } @Override public Collection getFunctions(String name) { return schema.getFunctions(name); } @Override public Set getFunctionNames() { return schema.getFunctionNames(); } @Override public Set getSubSchemaNames() { return schema.getSubSchemaNames(); } @Override public Expression getExpression(@Nullable SchemaPlus parentSchema, String name) { return schema.getExpression(parentSchema, name); } @Override public Schema snapshot(SchemaVersion version) { throw new UnsupportedOperationException(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy