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

com.hazelcast.org.apache.calcite.rel.core.Uncollect Maven / Gradle / Ivy

There is a newer version: 5.4.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 com.hazelcast.com.liance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.com.hazelcast.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.org.apache.calcite.rel.core;

import com.hazelcast.org.apache.calcite.plan.Convention;
import com.hazelcast.org.apache.calcite.plan.RelOptCluster;
import com.hazelcast.org.apache.calcite.plan.RelTraitSet;
import com.hazelcast.org.apache.calcite.rel.RelInput;
import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.RelWriter;
import com.hazelcast.org.apache.calcite.rel.SingleRel;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeFactory;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeField;
import com.hazelcast.org.apache.calcite.sql.SqlUnnestOperator;
import com.hazelcast.org.apache.calcite.sql.type.MapSqlType;
import com.hazelcast.org.apache.calcite.sql.type.SqlTypeName;

import com.hazelcast.com.google.com.hazelcast.com.on.collect.ImmutableList;

import java.util.Collections;
import java.util.List;

/**
 * Relational expression that unnests its input's columns into a relation.
 *
 * 

The input may have multiple columns, but each must be a multiset or * array. If {@code withOrdinality}, the output contains an extra * {@code ORDINALITY} column. * *

Like its inverse operation {@link Collect}, Uncollect is generally * invoked in a nested loop, driven by * {@link com.hazelcast.org.apache.calcite.rel.logical.LogicalCorrelate} or similar. */ public class Uncollect extends SingleRel { public final boolean withOrdinality; // To alias the items in Uncollect list, // i.e., "UNNEST(a, b, c) as T(d, e, f)" // outputs as row type Record(d, e, f) where the field "d" has element type of "a", // field "e" has element type of "b"(Presto dialect). // Without the aliases, the expression "UNNEST(a)" outputs row type // same with element type of "a". private final List itemAliases; //~ Constructors ----------------------------------------------------------- @Deprecated // to be removed before 2.0 public Uncollect(RelOptCluster cluster, RelTraitSet traitSet, RelNode child) { this(cluster, traitSet, child, false, Collections.emptyList()); } /** Creates an Uncollect. * *

Use {@link #create} unless you know what you're doing. */ public Uncollect(RelOptCluster cluster, RelTraitSet traitSet, RelNode input, boolean withOrdinality, List itemAliases) { super(cluster, traitSet, input); this.withOrdinality = withOrdinality; this.itemAliases = ImmutableList.copyOf(itemAliases); assert deriveRowType() != null : "invalid child rowtype"; } /** * Creates an Uncollect by parsing serialized output. */ public Uncollect(RelInput input) { this(input.getCluster(), input.getTraitSet(), input.getInput(), input.getBoolean("withOrdinality", false), Collections.emptyList()); } /** * Creates an Uncollect. * *

Each field of the input relational expression must be an array or * multiset. * * @param traitSet Trait set * @param input Input relational expression * @param withOrdinality Whether output should contain an ORDINALITY column * @param itemAliases Aliases for the operand items */ public static Uncollect create( RelTraitSet traitSet, RelNode input, boolean withOrdinality, List itemAliases) { final RelOptCluster cluster = input.getCluster(); return new Uncollect(cluster, traitSet, input, withOrdinality, itemAliases); } //~ Methods ---------------------------------------------------------------- @Override public RelWriter explainTerms(RelWriter pw) { return super.explainTerms(pw) .itemIf("withOrdinality", withOrdinality, withOrdinality); } @Override public final RelNode copy(RelTraitSet traitSet, List inputs) { return copy(traitSet, sole(inputs)); } public RelNode copy(RelTraitSet traitSet, RelNode input) { assert traitSet.containsIfApplicable(Convention.NONE); return new Uncollect(getCluster(), traitSet, input, withOrdinality, itemAliases); } protected RelDataType deriveRowType() { return deriveUncollectRowType(input, withOrdinality, itemAliases); } /** * Returns the row type returned by applying the 'UNNEST' operation to a * relational expression. * *

Each column in the relational expression must be a multiset of * structs or an array. The return type is the com.hazelcast.com.ination of expanding * element types from each column, plus an ORDINALITY column if {@code * withOrdinality}. If {@code itemAliases} is not empty, the element types * would not expand, each column element outputs as a whole (the return * type has same column types as input type). */ public static RelDataType deriveUncollectRowType(RelNode rel, boolean withOrdinality, List itemAliases) { RelDataType inputType = rel.getRowType(); assert inputType.isStruct() : inputType + " is not a struct"; boolean requireAlias = !itemAliases.isEmpty(); assert !requireAlias || itemAliases.size() == inputType.getFieldCount(); final List fields = inputType.getFieldList(); final RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory(); final RelDataTypeFactory.Builder builder = typeFactory.builder(); if (fields.size() == 1 && fields.get(0).getType().getSqlTypeName() == SqlTypeName.ANY) { // Component type is unknown to Uncollect, build a row type with input column name // and Any type. return builder .add(requireAlias ? itemAliases.get(0) : fields.get(0).getName(), SqlTypeName.ANY) .nullable(true) .build(); } for (int i = 0; i < fields.size(); i++) { RelDataTypeField field = fields.get(i); if (field.getType() instanceof MapSqlType) { builder.add(SqlUnnestOperator.MAP_KEY_COLUMN_NAME, field.getType().getKeyType()); builder.add(SqlUnnestOperator.MAP_VALUE_COLUMN_NAME, field.getType().getValueType()); } else { RelDataType ret = field.getType().getComponentType(); assert null != ret; if (requireAlias) { builder.add(itemAliases.get(i), ret); } else if (ret.isStruct()) { builder.addAll(ret.getFieldList()); } else { // Element type is not a record, use the field name of the element directly builder.add(field.getName(), ret); } } } if (withOrdinality) { builder.add(SqlUnnestOperator.ORDINALITY_COLUMN_NAME, SqlTypeName.INTEGER); } return builder.build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy