content: /*
   * 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 org.apache.calcite.adapter.enumerable;
  
  import org.apache.calcite.adapter.java.JavaTypeFactory;
  import org.apache.calcite.linq4j.tree.Expression;
  import org.apache.calcite.linq4j.tree.ParameterExpression;
  import org.apache.calcite.rel.RelCollation;
  import org.apache.calcite.rel.RelFieldCollation;
  import org.apache.calcite.rel.type.RelDataType;
  import org.apache.calcite.util.Pair;
  
  import org.checkerframework.checker.nullness.qual.Nullable;
  
  import java.lang.reflect.Type;
  import java.util.List;
  
  /**
   * Physical type of a row.
   *
   * <p>Consists of the SQL row type (returned by {@link #getRowType()}), the Java
   * type of the row (returned by {@link #getJavaRowType()}), and methods to
   * generate expressions to access fields, generate records, and so forth.
   * Together, the records encapsulate how the logical type maps onto the physical
   * type.
   */
  public interface PhysType {
    /** Returns the Java type (often a Class) that represents a row. For
     * example, in one row format, always returns {@code Object[].class}. */
    Type getJavaRowType();
  
    /**
     * Returns the Java class that is used to store the field with the given
     * ordinal.
     *
     * <p>For instance, when the java row type is {@code Object[]}, the java
     * field type is {@code Object} even if the field is not nullable. */
    Type getJavaFieldType(int field);
  
    /** Returns the type factory. */
    JavaTypeFactory getTypeFactory();
  
    /** Returns the physical type of a field. */
    PhysType field(int ordinal);
  
    /** Returns the physical type of a given field's component type. */
    PhysType component(int field);
  
    /** Returns the SQL row type. */
    RelDataType getRowType();
  
    /** Returns the Java class of the field with the given ordinal. */
    Class fieldClass(int field);
  
    /** Returns whether a given field allows null values. */
    boolean fieldNullable(int index);
  
    /** Generates a reference to a given field in an expression.
     *
     * <p>For example given {@code expression=employee} and {@code field=2},
     * generates
     *
     * <blockquote><pre>{@code employee.deptno}</pre></blockquote>
     *
     * @param expression Expression
     * @param field Ordinal of field
     * @return Expression to access the field of the expression
     */
    Expression fieldReference(Expression expression, int field);
  
    /** Generates a reference to a given field in an expression.
     *
     * <p>This method optimizes for the target storage type (i.e. avoids
     * casts).
     *
     * <p>For example given {@code expression=employee} and {@code field=2},
     * generates
     *
     * <blockquote><pre>{@code employee.deptno}</pre></blockquote>
     *
     * @param expression Expression
     * @param field Ordinal of field
     * @param storageType optional hint for storage class
     * @return Expression to access the field of the expression
     */
    Expression fieldReference(Expression expression, int field,
        @Nullable Type storageType);
  
    /** Generates an accessor function for a given list of fields.  The resulting
     * object is a {@link List} (implementing {@link Object#hashCode()} and
     * {@link Object#equals(Object)} per that interface) and also implements
     * {@link Comparable}.
     *
     * <p>For example:
     *
     * <blockquote><pre>
     * new Function1&lt;Employee, Object[]&gt; {
     *    public Object[] apply(Employee v1) {
     *        return FlatLists.of(v1.&lt;fieldN&gt;, v1.&lt;fieldM&gt;);
     *    }
     * }</pre></blockquote>
     */
    Expression generateAccessor(List<Integer> fields);
  
    /** Similar to {@link #generateAccessor(List)}, but if one of the fields is <code>null</code>,
     * it will return <code>null</code>.
     *
     * <p>For example:
     *
     * <blockquote><pre>
     * new Function1&lt;Employee, Object[]&gt; {
     *    public Object[] apply(Employee v1) {
     *        return v1.&lt;fieldN&gt; == null
     *            ? null
     *            : v1.&lt;fieldM&gt; == null
     *                ? null
     *                : FlatLists.of(v1.&lt;fieldN&gt;, v1.&lt;fieldM&gt;);
     *    }
     * }</pre></blockquote>
     */
    Expression generateAccessorWithoutNulls(List<Integer> fields);
  
    /** Generates a selector for the given fields from an expression, with the
     * default row format. */
    Expression generateSelector(
        ParameterExpression parameter,
        List<Integer> fields);
  
    /** Generates a lambda expression that is a selector for the given fields from
     * an expression. */
    Expression generateSelector(
        ParameterExpression parameter,
        List<Integer> fields,
        JavaRowFormat targetFormat);
  
    /** Generates a lambda expression that is a selector for the given fields from
     * an expression.
     *
     * <p>{@code usedFields} must be a subset of {@code fields}.
     * For each field, there is a corresponding indicator field.
     * If a field is used, its value is assigned and its indicator is left
     * {@code false}.
     * If a field is not used, its value is not assigned and its indicator is
     * set to {@code true};
     * This will become a value of 1 when {@code GROUPING(field)} is called. */
    Expression generateSelector(
        ParameterExpression parameter,
        List<Integer> fields,
        List<Integer> usedFields,
        JavaRowFormat targetFormat);
  
    /** Generates a selector for the given fields from an expression.
     * Only used by EnumerableWindow. */
    Pair<Type, List<Expression>> selector(
        ParameterExpression parameter,
        List<Integer> fields,
        JavaRowFormat targetFormat);
  
    /** Projects a given collection of fields from this input record, into
     * a particular preferred output format. The output format is optimized
     * if there are 0 or 1 fields. */
    PhysType project(
        List<Integer> integers,
        JavaRowFormat format);
  
    /** Projects a given collection of fields from this input record, optionally
     * with indicator fields, into a particular preferred output format.
     *
     * <p>The output format is optimized if there are 0 or 1 fields
     * and indicators are disabled. */
    PhysType project(
        List<Integer> integers,
        boolean indicator,
        JavaRowFormat format);
  
    /** Returns a lambda to create a collation key and a comparator. The
     * comparator is sometimes null. */
    Pair<Expression, Expression> generateCollationKey(
        List<RelFieldCollation> collations);
  
    /** Returns a comparator. Unlike the comparator returned by
     * {@link #generateCollationKey(java.util.List)}, this comparator acts on the
     * whole element. */
    Expression generateComparator(
        RelCollation collation);
  
    /** Similar to {@link #generateComparator(RelCollation)}, but with some specificities for
     * MergeJoin algorithm: it will not consider two <code>null</code> values as equal.
     *
     * @see org.apache.calcite.linq4j.EnumerableDefaults#compareNullsLastForMergeJoin
     */
    Expression generateMergeJoinComparator(RelCollation collation);
  
    /** Returns a expression that yields a comparer, or null if this type
     * is comparable. */
    @Nullable Expression comparer();
  
    /** Generates an expression that creates a record for a row, initializing
     * its fields with the given expressions. There must be one expression per
     * field.
     *
     * @param expressions Expression to initialize each field
     * @return Expression to create a row
     */
    Expression record(List<Expression> expressions);
  
    /** Returns the format. */
    JavaRowFormat getFormat();
  
    List<Expression> accessors(Expression parameter, List<Integer> argList);
  
    /** Returns a copy of this type that allows nulls if {@code nullable} is
     * true. */
    PhysType makeNullable(boolean nullable);
  
    /** Converts an enumerable of this physical type to an enumerable that uses a
     * given physical type for its rows.
     *
     * @deprecated Use {@link #convertTo(Expression, JavaRowFormat)}.
     * The use of PhysType as a second parameter is misleading since only the row
     * format of the expression is affected by the conversion. Moreover it requires
     * to have at hand a PhysType object which is not really necessary for achieving
     * the desired result. */
    @Deprecated // to be removed before 2.0
    Expression convertTo(Expression expression, PhysType targetPhysType);
  
    /** Converts an enumerable of this physical type to an enumerable that uses
     * the <code>targetFormat</code> for representing its rows. */
    Expression convertTo(Expression expression, JavaRowFormat targetFormat);
  }
  