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

org.apache.kylin.query.relnode.OLAPRel Maven / Gradle / Ivy

/*
 * 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.kylin.query.relnode;

import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Stack;

import org.apache.calcite.adapter.enumerable.EnumerableRel;
import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
import org.apache.calcite.plan.Convention;
import org.apache.calcite.plan.RelTrait;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 */
public interface OLAPRel extends RelNode {

    public static final Logger logger = LoggerFactory.getLogger(OLAPRel.class);

    // Calling convention for relational operations that occur in OLAP.
    public static final Convention CONVENTION = new Convention.Impl("OLAP", OLAPRel.class);

    /**
     * get olap context
     */
    public OLAPContext getContext();

    /**
     * get the row type of ColumnDesc
     * 
     * @return
     */
    public ColumnRowType getColumnRowType();

    /**
     * whether has sub query
     */
    public boolean hasSubQuery();

    /**
     * replace RelTraitSet
     */
    public RelTraitSet replaceTraitSet(RelTrait trait);

    /**
     * visitor pattern for olap query analysis
     */
    public static class OLAPImplementor {

        private RelNode parentNode = null;
        private int ctxSeq = 0;
        private Stack ctxStack = new Stack();

        public void visitChild(RelNode input, RelNode parentNode) {
            this.parentNode = parentNode;
            ((OLAPRel) input).implementOLAP(this);
        }

        public RelNode getParentNode() {
            return parentNode;
        }

        public OLAPContext getContext() {
            if (ctxStack.isEmpty()) {
                return null;
            }
            return ctxStack.peek();
        }

        public void freeContext() {
            ctxStack.pop();
        }

        public void allocateContext() {
            OLAPContext context = new OLAPContext(ctxSeq++);
            ctxStack.push(context);
            OLAPContext.registerContext(context);
        }
    }

    public void implementOLAP(OLAPImplementor implementor);

    /**
     * visitor pattern for query rewrite
     */

    public static class RewriteImplementor {
        private OLAPContext parentContext;

        public void visitChild(RelNode parent, RelNode child) {
            if (parent instanceof OLAPRel) {
                OLAPRel olapRel = (OLAPRel) parent;
                this.parentContext = olapRel.getContext();
            }
            OLAPRel olapChild = (OLAPRel) child;
            olapChild.implementRewrite(this);
        }

        public OLAPContext getParentContext() {
            return parentContext;
        }

        public static boolean needRewrite(OLAPContext ctx) {
            boolean hasFactTable = ctx.hasJoin || ctx.firstTableScan.getTableName().equals(ctx.realization.getFactTable());
            boolean hasRewriteFields = !ctx.rewriteFields.isEmpty();
            return hasRewriteFields && hasFactTable;
        }
    }

    public void implementRewrite(RewriteImplementor rewriter);

    /**
     * implementor for java generation
     */
    public static class JavaImplementor extends EnumerableRelImplementor {

        private IdentityHashMap relContexts = Maps.newIdentityHashMap();
        private boolean calciteDebug = System.getProperty("calcite.debug") != null;

        public JavaImplementor(EnumerableRelImplementor enumImplementor) {
            super(enumImplementor.getRexBuilder(), new LinkedHashMap());
        }

        public EnumerableRel createEnumerable(OLAPRel parent) {
            ArrayList enumInputs = null;
            List children = parent.getInputs();
            if (children != null) {
                enumInputs = Lists.newArrayListWithCapacity(children.size());
                for (RelNode child : children) {
                    enumInputs.add(createEnumerable((OLAPRel) child));
                }
            }

            EnumerableRel result = parent.implementEnumerable(enumInputs);
            relContexts.put(result, parent.getContext());
            return result;
        }

        @Override
        public EnumerableRel.Result visitChild(EnumerableRel parent, int ordinal, EnumerableRel child, EnumerableRel.Prefer prefer) {
            // OLAPTableScan is shared instance when the same table appears multiple times in the tree.
            // Its context must be set (or corrected) right before visiting.
            if (child instanceof OLAPTableScan) {
                OLAPContext parentContext = relContexts.get(parent);
                if (parentContext != null) {
                    ((OLAPTableScan) child).overrideContext(parentContext);
                }
            }

            if (calciteDebug) {
                OLAPContext context;
                if (child instanceof OLAPRel)
                    context = ((OLAPRel) child).getContext();
                else
                    context = relContexts.get(child);
                System.out.println(context + " - " + child);
            }

            return super.visitChild(parent, ordinal, child, prefer);
        }
    }

    public EnumerableRel implementEnumerable(List inputs);

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy