| /* |
| * 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.carbondata.core.scan.filter.resolver; |
| |
| import java.util.List; |
| |
| import org.apache.carbondata.core.datastore.block.SegmentProperties; |
| import org.apache.carbondata.core.metadata.datatype.DataTypes; |
| import org.apache.carbondata.core.scan.expression.ColumnExpression; |
| import org.apache.carbondata.core.scan.expression.Expression; |
| import org.apache.carbondata.core.scan.expression.conditional.BinaryConditionalExpression; |
| import org.apache.carbondata.core.scan.expression.conditional.ConditionalExpression; |
| import org.apache.carbondata.core.scan.expression.exception.FilterUnsupportedException; |
| import org.apache.carbondata.core.scan.expression.logical.RangeExpression; |
| import org.apache.carbondata.core.scan.filter.FilterUtil; |
| import org.apache.carbondata.core.scan.filter.intf.FilterExecuterType; |
| import org.apache.carbondata.core.scan.filter.resolver.metadata.FilterResolverMetadata; |
| import org.apache.carbondata.core.scan.filter.resolver.resolverinfo.DimColumnResolvedFilterInfo; |
| import org.apache.carbondata.core.scan.filter.resolver.resolverinfo.MeasureColumnResolvedFilterInfo; |
| import org.apache.carbondata.core.scan.filter.resolver.resolverinfo.visitor.FilterInfoTypeVisitorFactory; |
| |
| public class ConditionalFilterResolverImpl implements FilterResolverIntf { |
| |
| private static final long serialVersionUID = 1838955268462201691L; |
| protected Expression exp; |
| protected boolean isExpressionResolve; |
| protected boolean isIncludeFilter; |
| private DimColumnResolvedFilterInfo dimColResolvedFilterInfo; |
| private MeasureColumnResolvedFilterInfo msrColResolvedFilterInfo; |
| |
| public ConditionalFilterResolverImpl(Expression exp, boolean isExpressionResolve, |
| boolean isIncludeFilter, boolean isMeasure) { |
| this.exp = exp; |
| this.isExpressionResolve = isExpressionResolve; |
| this.isIncludeFilter = isIncludeFilter; |
| if (!isMeasure) { |
| this.dimColResolvedFilterInfo = new DimColumnResolvedFilterInfo(); |
| } else { |
| this.msrColResolvedFilterInfo = new MeasureColumnResolvedFilterInfo(); |
| } |
| } |
| |
| |
| /** |
| * This API will resolve the filter expression and generates the |
| * dictionaries for executing/evaluating the filter expressions in the |
| * executer layer. |
| * |
| * @throws FilterUnsupportedException |
| */ |
| @Override |
| public void resolve() |
| throws FilterUnsupportedException { |
| FilterResolverMetadata metadata = new FilterResolverMetadata(); |
| if ((!isExpressionResolve) && exp instanceof BinaryConditionalExpression) { |
| BinaryConditionalExpression binaryConditionalExpression = (BinaryConditionalExpression) exp; |
| Expression leftExp = binaryConditionalExpression.getLeft(); |
| Expression rightExp = binaryConditionalExpression.getRight(); |
| if (leftExp instanceof ColumnExpression) { |
| ColumnExpression columnExpression = (ColumnExpression) leftExp; |
| metadata.setColumnExpression(columnExpression); |
| metadata.setExpression(rightExp); |
| metadata.setIncludeFilter(isIncludeFilter); |
| // If imei=imei comes in filter condition then we need to |
| // skip processing of right expression. |
| // This flow has reached here assuming that this is a single |
| // column expression. |
| // we need to check if the other expression contains column |
| // expression or not in depth. |
| if (FilterUtil.checkIfExpressionContainsColumn(rightExp)) { |
| isExpressionResolve = true; |
| } else { |
| //Visitor pattern is been used in this scenario inorder to populate the |
| // dimColResolvedFilterInfo |
| //visitable object with filter member values based on the visitor type, currently there |
| //3 types of visitors custom,direct and no dictionary, all types of visitor populate |
| //the visitable instance as per its buisness logic which is different for all the |
| // visitors. |
| if (columnExpression.isMeasure()) { |
| msrColResolvedFilterInfo.setMeasure(columnExpression.getMeasure()); |
| msrColResolvedFilterInfo.populateFilterInfoBasedOnColumnType( |
| FilterInfoTypeVisitorFactory.getResolvedFilterInfoVisitor(columnExpression, exp), |
| metadata); |
| } else { |
| dimColResolvedFilterInfo.populateFilterInfoBasedOnColumnType( |
| FilterInfoTypeVisitorFactory.getResolvedFilterInfoVisitor(columnExpression, exp), |
| metadata); |
| } |
| } |
| } else if (rightExp instanceof ColumnExpression) { |
| ColumnExpression columnExpression = (ColumnExpression) rightExp; |
| metadata.setColumnExpression(columnExpression); |
| metadata.setExpression(leftExp); |
| metadata.setIncludeFilter(isIncludeFilter); |
| if (columnExpression.getDataType().equals(DataTypes.TIMESTAMP) || |
| columnExpression.getDataType().equals(DataTypes.DATE)) { |
| isExpressionResolve = true; |
| } else { |
| // if imei=imei comes in filter condition then we need to |
| // skip processing of right expression. |
| // This flow has reached here assuming that this is a single |
| // column expression. |
| // we need to check if the other expression contains column |
| // expression or not in depth. |
| if (FilterUtil.checkIfExpressionContainsColumn(leftExp)) { |
| isExpressionResolve = true; |
| } else { |
| |
| if (columnExpression.isMeasure()) { |
| msrColResolvedFilterInfo.populateFilterInfoBasedOnColumnType( |
| FilterInfoTypeVisitorFactory.getResolvedFilterInfoVisitor(columnExpression, exp), |
| metadata); |
| } else { |
| dimColResolvedFilterInfo.populateFilterInfoBasedOnColumnType( |
| FilterInfoTypeVisitorFactory.getResolvedFilterInfoVisitor(columnExpression, exp), |
| metadata); |
| } |
| } |
| } |
| } else { |
| isExpressionResolve = true; |
| } |
| } |
| if (isExpressionResolve && exp instanceof ConditionalExpression) { |
| ConditionalExpression conditionalExpression = (ConditionalExpression) exp; |
| List<ColumnExpression> columnList = conditionalExpression.getColumnList(); |
| metadata.setColumnExpression(columnList.get(0)); |
| metadata.setExpression(exp); |
| metadata.setIncludeFilter(isIncludeFilter); |
| if ((null != columnList.get(0).getDimension()) || (exp instanceof RangeExpression)) { |
| dimColResolvedFilterInfo.populateFilterInfoBasedOnColumnType( |
| FilterInfoTypeVisitorFactory.getResolvedFilterInfoVisitor(columnList.get(0), exp), |
| metadata); |
| } else if (columnList.get(0).isMeasure()) { |
| msrColResolvedFilterInfo.setMeasure(columnList.get(0).getMeasure()); |
| msrColResolvedFilterInfo.populateFilterInfoBasedOnColumnType( |
| FilterInfoTypeVisitorFactory.getResolvedFilterInfoVisitor(columnList.get(0), exp), |
| metadata); |
| msrColResolvedFilterInfo.setCarbonColumn(columnList.get(0).getCarbonColumn()); |
| msrColResolvedFilterInfo.setColumnIndex(columnList.get(0).getCarbonColumn().getOrdinal()); |
| msrColResolvedFilterInfo.setType(columnList.get(0).getCarbonColumn().getDataType()); |
| } |
| } |
| |
| } |
| |
| /** |
| * Left node will not be presentin this scenario |
| * |
| * @return left node of type FilterResolverIntf instance |
| */ |
| public FilterResolverIntf getLeft() { |
| // TODO Auto-generated method stub |
| return null; |
| } |
| |
| /** |
| * Right node will not be presentin this scenario |
| * |
| * @return left node of type FilterResolverIntf instance |
| */ |
| @Override |
| public FilterResolverIntf getRight() { |
| // TODO Auto-generated method stub |
| return null; |
| } |
| |
| /** |
| * Method will return the DimColumnResolvedFilterInfo instance which consists |
| * the mapping of the respective dimension and its surrogates involved in |
| * filter expression. |
| * |
| * @return DimColumnResolvedFilterInfo |
| */ |
| public DimColumnResolvedFilterInfo getDimColResolvedFilterInfo() { |
| return dimColResolvedFilterInfo; |
| } |
| |
| /** |
| * Method will return the MeasureColumnResolvedFilterInfo instance which consists |
| * the mapping of the respective dimension and its surrogates involved in |
| * filter expression. |
| * |
| * @return DimColumnResolvedFilterInfo |
| */ |
| public MeasureColumnResolvedFilterInfo getMsrColResolvedFilterInfo() { |
| return msrColResolvedFilterInfo; |
| } |
| |
| /** |
| * Method will return the executer type for particular conditional resolver |
| * basically two types of executers will be formed for the conditional query. |
| * |
| * @return the filter executer type |
| */ |
| @Override |
| public FilterExecuterType getFilterExecuterType() { |
| switch (exp.getFilterExpressionType()) { |
| case NOT_EQUALS: |
| case NOT_IN: |
| return FilterExecuterType.EXCLUDE; |
| case RANGE: |
| return FilterExecuterType.RANGE; |
| default: |
| return FilterExecuterType.INCLUDE; |
| } |
| |
| } |
| |
| /** |
| * This method will return the filter values which is present in the range level |
| * conditional expressions. |
| * |
| * @return |
| */ |
| public byte[][] getFilterRangeValues(SegmentProperties segmentProperties) { |
| |
| if (null != dimColResolvedFilterInfo.getFilterValues() && |
| dimColResolvedFilterInfo.getDimension().getDataType() != DataTypes.DATE) { |
| List<byte[]> noDictFilterValuesList = |
| dimColResolvedFilterInfo.getFilterValues().getNoDictionaryFilterValuesList(); |
| return noDictFilterValuesList.toArray((new byte[noDictFilterValuesList.size()][])); |
| } else if (null != dimColResolvedFilterInfo.getFilterValues() && |
| dimColResolvedFilterInfo.getDimension().getDataType() == DataTypes.DATE) { |
| return FilterUtil.getKeyArray(this.dimColResolvedFilterInfo.getFilterValues(), |
| this.dimColResolvedFilterInfo.getDimension(), segmentProperties, false, false); |
| } |
| return null; |
| } |
| |
| @Override |
| public Expression getFilterExpression() { |
| // TODO Auto-generated method stub |
| return exp; |
| } |
| |
| } |