Package com.foundationdb.sql.optimizer.rule.range

Source Code of com.foundationdb.sql.optimizer.rule.range.ColumnRanges

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.sql.optimizer.rule.range;

import com.foundationdb.server.types.texpressions.Comparison;
import com.foundationdb.sql.optimizer.plan.ColumnExpression;
import com.foundationdb.sql.optimizer.plan.ComparisonCondition;
import com.foundationdb.sql.optimizer.plan.ConditionExpression;
import com.foundationdb.sql.optimizer.plan.ConstantExpression;
import com.foundationdb.sql.optimizer.plan.ExpressionNode;
import com.foundationdb.sql.optimizer.plan.FunctionCondition;
import com.foundationdb.sql.optimizer.plan.InListCondition;
import com.foundationdb.sql.optimizer.plan.LogicalFunctionCondition;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public final class ColumnRanges {

    public static ColumnRanges rangeAtNode(ConditionExpression node) {
        if (node instanceof ComparisonCondition) {
            ComparisonCondition comparisonCondition = (ComparisonCondition) node;
            return comparisonToRange(comparisonCondition);
        }
        else if (node instanceof LogicalFunctionCondition) {
            LogicalFunctionCondition condition = (LogicalFunctionCondition) node;
            if (condition.getOperands().size() != 2)
                return null;
            ColumnRanges leftRange = rangeAtNode(condition.getLeft());
            ColumnRanges rightRange = rangeAtNode(condition.getRight());
            if (leftRange != null && rightRange != null) {
                List<RangeSegment> combinedSegments = combineBool(leftRange, rightRange, condition.getFunction());
                if (combinedSegments != null) {
                    return new ColumnRanges(leftRange.getColumnExpression(), condition, combinedSegments);
                }
            }
        }
        else if (node instanceof FunctionCondition) {
            FunctionCondition condition = (FunctionCondition) node;
            if ("isNull".equals(condition.getFunction())) {
                if (condition.getOperands().size() == 1) {
                    ExpressionNode operand = condition.getOperands().get(0);
                    if (operand instanceof ColumnExpression) {
                        ColumnExpression operandColumn = (ColumnExpression) operand;
                        return new ColumnRanges(operandColumn, condition,
                                Collections.singletonList(RangeSegment.onlyNull(operandColumn)));
                    }
                }
            }
        }
        else if (node instanceof InListCondition) {
            InListCondition inListCondition = (InListCondition) node;
            return inListToRange(inListCondition);
        }
        return null;
    }

    public static ColumnRanges andRanges(ColumnRanges left, ColumnRanges right) {
        List<RangeSegment> combinedSegments = combineBool(left, right, true);
        if (combinedSegments == null)
            return null;
        Set<ConditionExpression> combinedConditions = new HashSet<>(left.getConditions());
        combinedConditions.addAll(right.getConditions());
        return new ColumnRanges(left.getColumnExpression(), combinedConditions, combinedSegments);
    }

    private static List<RangeSegment> combineBool(ColumnRanges leftRange, ColumnRanges rightRange, boolean isAnd) {
        if (!leftRange.getColumnExpression().equals(rightRange.getColumnExpression()))
            return null;
        List<RangeSegment> leftSegments = leftRange.getSegments();
        List<RangeSegment> rightSegments = rightRange.getSegments();
        List<RangeSegment> result;
        if (isAnd)
            result = RangeSegment.andRanges(leftSegments, rightSegments);
        else
            result = RangeSegment.orRanges(leftSegments, rightSegments);
        if (result != null)
            result = RangeSegment.sortAndCombine(result);
        return result;
    }
   
    private static List<RangeSegment> combineBool(ColumnRanges leftRange, ColumnRanges rightRange, String logicOp) {
        logicOp = logicOp.toLowerCase();
        if ("and".endsWith(logicOp))
            return combineBool(leftRange, rightRange, true);
        else if ("or".equals(logicOp))
            return combineBool(leftRange, rightRange, false);
        else
            return null;
    }

    public Collection<? extends ConditionExpression> getConditions() {
        return rootConditions;
    }

    public List<RangeSegment> getSegments() {
        return segments;
    }

    public ColumnExpression getColumnExpression() {
        return columnExpression;
    }

    public String describeRanges() {
        return segments.toString();
    }

    public boolean isAllSingle() {
        boolean all = true;
        for (RangeSegment segment : segments) {
            if (!segment.isSingle()) {
                return false;
            }
        }
        return all;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ColumnRanges that = (ColumnRanges) o;

        return columnExpression.equals(that.columnExpression)
                && rootConditions.equals(that.rootConditions)
                && segments.equals(that.segments);

    }

    @Override
    public int hashCode() {
        int result = columnExpression.hashCode();
        result = 31 * result + rootConditions.hashCode();
        result = 31 * result + segments.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "Range " + columnExpression + ' ' + segments;
    }

    public ColumnRanges(ColumnExpression columnExpression, Set<? extends ConditionExpression> rootConditions,
                        List<RangeSegment> segments)
    {
        this.columnExpression = columnExpression;
        this.rootConditions = rootConditions;
        this.segments = segments;
    }

    public ColumnRanges(ColumnExpression columnExpression, ConditionExpression rootCondition,
                        List<RangeSegment> segments) {
        this(columnExpression, Collections.singleton(rootCondition), segments);
    }

    private static ColumnRanges comparisonToRange(ComparisonCondition comparisonCondition) {
        final ColumnExpression columnExpression;
        final ExpressionNode other;
        final boolean columnIsRight;
        if (comparisonCondition.getLeft() instanceof ColumnExpression) {
            columnExpression = (ColumnExpression) comparisonCondition.getLeft();
            other = comparisonCondition.getRight();
            columnIsRight = false;
        }
        else if (comparisonCondition.getRight() instanceof ColumnExpression) {
            columnExpression = (ColumnExpression) comparisonCondition.getRight();
            other = comparisonCondition.getLeft();
            columnIsRight = true;
        }
        else {
            return null;
        }
        if (other instanceof ConstantExpression) {
            ConstantExpression constant = (ConstantExpression) other;
            Comparison op = comparisonCondition.getOperation();
            if (columnIsRight) {
                op = flip(op);
            }
            List<RangeSegment> rangeSegments = RangeSegment.fromComparison(op, constant);
            return new ColumnRanges(columnExpression, comparisonCondition, rangeSegments);
        }
        else {
            return null;
        }
    }

    private static Comparison flip(Comparison op) {
        switch (op) {
            case LT:    return Comparison.GT;
            case LE:    return Comparison.GE;
            case GT:    return Comparison.LT;
            case GE:    return Comparison.LE;
            case EQ:
            case NE:    return op;
            default:    throw new AssertionError(op.name());
        }
    }

    private static ColumnRanges inListToRange(InListCondition inListCondition) {
        final ColumnExpression columnExpression;
        if (inListCondition.getOperand() instanceof ColumnExpression) {
            columnExpression = (ColumnExpression)inListCondition.getOperand();
        }
        else {
            return null;
        }
        List<ExpressionNode> expressions = inListCondition.getExpressions();
        List<RangeSegment> rangeSegments = new ArrayList<>(expressions.size());
        for (ExpressionNode expr : expressions) {
            if (expr instanceof ConstantExpression) {
                rangeSegments.addAll(RangeSegment.fromComparison(Comparison.EQ,
                                                                 (ConstantExpression)expr));
            }
            else {
                return null;
            }
        }
        return new ColumnRanges(columnExpression, inListCondition, rangeSegments);
    }

    private ColumnExpression columnExpression;
    private Set<? extends ConditionExpression> rootConditions;
    private List<RangeSegment> segments;
}
TOP

Related Classes of com.foundationdb.sql.optimizer.rule.range.ColumnRanges

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.