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

com.hazelcast.org.apache.calcite.rel.rules.IntersectToDistinctRule 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.org.apache.calcite.rel.rules;

import com.hazelcast.org.apache.calcite.plan.RelOptCluster;
import com.hazelcast.org.apache.calcite.plan.RelOptRuleCall;
import com.hazelcast.org.apache.calcite.plan.RelRule;
import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.core.Intersect;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalIntersect;
import com.hazelcast.org.apache.calcite.rex.RexBuilder;
import com.hazelcast.org.apache.calcite.tools.RelBuilder;
import com.hazelcast.org.apache.calcite.tools.RelBuilderFactory;
import com.hazelcast.org.apache.calcite.util.ImmutableBitSet;
import com.hazelcast.org.apache.calcite.util.Util;

import org.immutables.value.Value;

import java.math.BigDecimal;

/**
 * Planner rule that translates a distinct
 * {@link com.hazelcast.org.apache.calcite.rel.core.Intersect}
 * (all = false)
 * into a group of operators composed of
 * {@link com.hazelcast.org.apache.calcite.rel.core.Union},
 * {@link com.hazelcast.org.apache.calcite.rel.core.Aggregate}, etc.
 *
 * 

Rewrite: (GB-Union All-GB)-GB-UDTF (on all attributes) * *

Example

* *

Query: R1 Intersect All R2 * *

R3 = GB(R1 on all attributes, count(*) as c)
* union all
* GB(R2 on all attributes, count(*) as c)
* *

R4 = GB(R3 on all attributes, count(c) as cnt, min(c) as m) * *

Note that we do not need min(c) in intersect distinct. * *

R5 = Filter(cnt == #branch) * *

If it is intersect all then * *

R6 = UDTF (R5) which will explode the tuples based on min(c)
* R7 = Project(R6 on all attributes)
* *

Else * *

R6 = Proj(R5 on all attributes) * * @see com.hazelcast.org.apache.calcite.rel.rules.UnionToDistinctRule * @see CoreRules#INTERSECT_TO_DISTINCT */ @Value.Enclosing public class IntersectToDistinctRule extends RelRule implements TransformationRule { /** Creates an IntersectToDistinctRule. */ protected IntersectToDistinctRule(Config config) { super(config); } @Deprecated // to be removed before 2.0 public IntersectToDistinctRule(Class intersectClass, RelBuilderFactory relBuilderFactory) { this(Config.DEFAULT.withRelBuilderFactory(relBuilderFactory) .as(Config.class) .withOperandFor(intersectClass)); } //~ Methods ---------------------------------------------------------------- @Override public void onMatch(RelOptRuleCall call) { final Intersect intersect = call.rel(0); if (intersect.all) { return; // nothing we can do } final RelOptCluster cluster = intersect.getCluster(); final RexBuilder rexBuilder = cluster.getRexBuilder(); final RelBuilder relBuilder = call.builder(); // 1st level GB: create a GB (col0, col1, count() as c) for each branch for (RelNode input : intersect.getInputs()) { relBuilder.push(input); relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()), relBuilder.countStar(null)); } // create a union above all the branches final int branchCount = intersect.getInputs().size(); relBuilder.union(true, branchCount); final RelNode union = relBuilder.peek(); // 2nd level GB: create a GB (col0, col1, count(c)) for each branch // the index of c is union.getRowType().getFieldList().size() - 1 final int fieldCount = union.getRowType().getFieldCount(); final ImmutableBitSet groupSet = ImmutableBitSet.range(fieldCount - 1); relBuilder.aggregate(relBuilder.groupKey(groupSet), relBuilder.countStar(null)); // add a filter count(c) = #branches relBuilder.filter( relBuilder.equals(relBuilder.field(fieldCount - 1), rexBuilder.makeBigintLiteral(new BigDecimal(branchCount)))); // Project all but the last field relBuilder.project(Util.skipLast(relBuilder.fields())); // the schema for intersect distinct is like this // R3 on all attributes + count(c) as cnt // finally add a project to project out the last column call.transformTo(relBuilder.build()); } /** Rule configuration. */ @Value.Immutable public interface Config extends RelRule.Config { Config DEFAULT = ImmutableIntersectToDistinctRule.Config.of() .withOperandFor(LogicalIntersect.class); @Override default IntersectToDistinctRule toRule() { return new IntersectToDistinctRule(this); } /** Defines an operand tree for the given classes. */ default Config withOperandFor(Class intersectClass) { return withOperandSupplier(b -> b.operand(intersectClass).anyInputs()) .as(Config.class); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy