You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@carbondata.apache.org by ch...@apache.org on 2016/06/30 17:42:34 UTC
[47/50] [abbrv] incubator-carbondata git commit: Merge
remote-tracking branch 'carbon_master/master' into apache/master
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/executor/util/QueryUtil.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/executor/util/QueryUtil.java
index a7d98a3,0000000..d3423b0
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/executor/util/QueryUtil.java
+++ b/core/src/main/java/org/carbondata/scan/executor/util/QueryUtil.java
@@@ -1,718 -1,0 +1,755 @@@
+/*
+ * 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.carbondata.scan.executor.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.carbondata.core.cache.Cache;
+import org.carbondata.core.cache.CacheProvider;
+import org.carbondata.core.cache.CacheType;
+import org.carbondata.core.cache.dictionary.Dictionary;
+import org.carbondata.core.cache.dictionary.DictionaryColumnUniqueIdentifier;
+import org.carbondata.core.carbon.AbsoluteTableIdentifier;
+import org.carbondata.core.carbon.CarbonTableIdentifier;
+import org.carbondata.core.carbon.datastore.block.SegmentProperties;
+import org.carbondata.core.carbon.metadata.CarbonMetadata;
+import org.carbondata.core.carbon.metadata.encoder.Encoding;
+import org.carbondata.core.carbon.metadata.schema.table.CarbonTable;
+import org.carbondata.core.carbon.metadata.schema.table.column.CarbonDimension;
+import org.carbondata.core.carbon.metadata.schema.table.column.CarbonMeasure;
+import org.carbondata.core.constants.CarbonCommonConstants;
+import org.carbondata.core.keygenerator.KeyGenException;
+import org.carbondata.core.keygenerator.KeyGenerator;
+import org.carbondata.core.util.CarbonUtil;
+import org.carbondata.core.util.CarbonUtilException;
+import org.carbondata.scan.executor.exception.QueryExecutionException;
+import org.carbondata.scan.executor.infos.KeyStructureInfo;
++import org.carbondata.scan.filter.resolver.resolverinfo.DimColumnResolvedFilterInfo;
+import org.carbondata.scan.model.QueryDimension;
+import org.carbondata.scan.model.QueryMeasure;
+import org.carbondata.scan.model.QueryModel;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * Utility class for query execution
+ */
+public class QueryUtil {
+
+ /**
+ * Below method will be used to get the masked byte range based on the query
+ * dimension. It will give the range in the mdkey. This will be used to get
+ * the actual key array from masked mdkey
+ *
+ * @param queryDimensions query dimension selected in query
+ * @param keyGenerator key generator
+ * @return masked key
+ */
+ public static int[] getMaskedByteRange(List<QueryDimension> queryDimensions,
+ KeyGenerator keyGenerator) {
+ Set<Integer> byteRangeSet = new TreeSet<Integer>();
+ int[] byteRange = null;
+ for (int i = 0; i < queryDimensions.size(); i++) {
+
+ // as no dictionary column and complex type columns
+ // are not selected in the mdkey
+ // so we will not select the those dimension for calculating the
+ // range
+ if (queryDimensions.get(i).getDimension().getKeyOrdinal() == -1) {
+ continue;
+ }
+ // get the offset of the dimension in the mdkey
+ byteRange =
+ keyGenerator.getKeyByteOffsets(queryDimensions.get(i).getDimension().getKeyOrdinal());
+ for (int j = byteRange[0]; j <= byteRange[1]; j++) {
+ byteRangeSet.add(j);
+ }
+ }
+ int[] maksedByteRange = new int[byteRangeSet.size()];
+ int index = 0;
+ Iterator<Integer> iterator = byteRangeSet.iterator();
+ // add the masked byte range
+ while (iterator.hasNext()) {
+ maksedByteRange[index++] = iterator.next();
+ }
+ return maksedByteRange;
+ }
+
+ public static int[] getMaskedByteRangeBasedOrdinal(List<Integer> ordinals,
+ KeyGenerator keyGenerator) {
+ Set<Integer> byteRangeSet = new TreeSet<Integer>();
+ int[] byteRange = null;
+ for (int i = 0; i < ordinals.size(); i++) {
+
+ // get the offset of the dimension in the mdkey
+ byteRange = keyGenerator.getKeyByteOffsets(ordinals.get(i));
+ for (int j = byteRange[0]; j <= byteRange[1]; j++) {
+ byteRangeSet.add(j);
+ }
+ }
+ int[] maksedByteRange = new int[byteRangeSet.size()];
+ int index = 0;
+ Iterator<Integer> iterator = byteRangeSet.iterator();
+ // add the masked byte range
+ while (iterator.hasNext()) {
+ maksedByteRange[index++] = iterator.next();
+ }
+ return maksedByteRange;
+ }
+
+ /**
+ * Below method will return the max key based on the dimension ordinal
+ *
+ * @param keyOrdinalList
+ * @param generator
+ * @return
+ * @throws KeyGenException
+ */
+ public static byte[] getMaxKeyBasedOnOrinal(List<Integer> keyOrdinalList, KeyGenerator generator)
+ throws KeyGenException {
+ long[] max = new long[generator.getDimCount()];
+ Arrays.fill(max, 0L);
+
+ for (int i = 0; i < keyOrdinalList.size(); i++) {
+ // adding for dimension which is selected in query
+ max[keyOrdinalList.get(i)] = Long.MAX_VALUE;
+ }
+ return generator.generateKey(max);
+ }
+
+ /**
+ * To get the max key based on dimensions. i.e. all other dimensions will be
+ * set to 0 bits and the required query dimension will be masked with all
+ * LONG.MAX so that we can mask key and then compare while aggregating This
+ * can be useful during filter query when only few dimensions were selected
+ * out of row group
+ *
+ * @param queryDimensions dimension selected in query
+ * @param generator key generator
+ * @return max key for dimension
+ * @throws KeyGenException if any problem while generating the key
+ */
+ public static byte[] getMaxKeyBasedOnDimensions(List<QueryDimension> queryDimensions,
+ KeyGenerator generator) throws KeyGenException {
+ long[] max = new long[generator.getDimCount()];
+ Arrays.fill(max, 0L);
+
+ for (int i = 0; i < queryDimensions.size(); i++) {
+ // as no dictionary column and complex type columns
+ // are not selected in the mdkey
+ // so we will not select the those dimension for calculating the
+ // range
+ if (queryDimensions.get(i).getDimension().getKeyOrdinal() == -1) {
+ continue;
+ }
+ // adding for dimension which is selected in query
+ max[queryDimensions.get(i).getDimension().getKeyOrdinal()] = Long.MAX_VALUE;
+ }
+
+ return generator.generateKey(max);
+ }
+
+ /**
+ * Below method will be used to get the masked key for query
+ *
+ * @param keySize size of the masked key
+ * @param maskedKeyRanges masked byte range
+ * @return masked bytes
+ */
+ public static int[] getMaskedByte(int keySize, int[] maskedKeyRanges) {
+ int[] maskedKey = new int[keySize];
+ // all the non selected dimension will be filled with -1
+ Arrays.fill(maskedKey, -1);
+ for (int i = 0; i < maskedKeyRanges.length; i++) {
+ maskedKey[maskedKeyRanges[i]] = i;
+ }
+ return maskedKey;
+ }
+
+ /**
+ * Below method will be used to get the dimension block index in file based
+ * on query dimension
+ *
+ * @param queryDimensions query dimension
+ * @param dimensionOrdinalToBlockMapping mapping of dimension block in file to query dimension
+ * @return block index of file
+ */
+ public static int[] getDimensionsBlockIndexes(List<QueryDimension> queryDimensions,
+ Map<Integer, Integer> dimensionOrdinalToBlockMapping,
+ List<CarbonDimension> customAggregationDimension) {
+ // using set as in row group columns will point to same block
+ Set<Integer> dimensionBlockIndex = new HashSet<Integer>();
+ for (int i = 0; i < queryDimensions.size(); i++) {
+ dimensionBlockIndex.add(
+ dimensionOrdinalToBlockMapping.get(queryDimensions.get(i).getDimension().getOrdinal()));
+ }
+ for (int i = 0; i < customAggregationDimension.size(); i++) {
+ dimensionBlockIndex
+ .add(dimensionOrdinalToBlockMapping.get(customAggregationDimension.get(i).getOrdinal()));
+ }
+ return ArrayUtils
+ .toPrimitive(dimensionBlockIndex.toArray(new Integer[dimensionBlockIndex.size()]));
+ }
+
+ /**
+ * Below method will be used to get the dictionary mapping for all the
+ * dictionary encoded dimension present in the query
+ *
+ * @param queryDimensions query dimension present in the query this will be used to
+ * convert the result from surrogate key to actual data
+ * @param absoluteTableIdentifier absolute table identifier
+ * @return dimension unique id to its dictionary map
+ * @throws QueryExecutionException
+ */
+ public static Map<String, Dictionary> getDimensionDictionaryDetail(
+ List<QueryDimension> queryDimensions,
+ AbsoluteTableIdentifier absoluteTableIdentifier) throws QueryExecutionException {
+ // to store dimension unique column id list, this is required as
+ // dimension can be present in
+ // query dimension, as well as some aggregation function will be applied
+ // in the same dimension
+ // so we need to get only one instance of dictionary
+ // direct dictionary skip is done only for the dictionary lookup
+ Set<String> dictionaryDimensionFromQuery = new HashSet<String>();
+ for (int i = 0; i < queryDimensions.size(); i++) {
+ List<Encoding> encodingList = queryDimensions.get(i).getDimension().getEncoder();
+ if (CarbonUtil.hasEncoding(encodingList, Encoding.DICTIONARY) && !CarbonUtil
+ .hasEncoding(encodingList, Encoding.DIRECT_DICTIONARY)) {
+ dictionaryDimensionFromQuery.add(queryDimensions.get(i).getDimension().getColumnId());
+ }
+ }
+ // converting to list as api exposed needed list which i think
+ // is not correct
+ List<String> dictionaryColumnIdList =
+ new ArrayList<String>(dictionaryDimensionFromQuery.size());
+ dictionaryColumnIdList.addAll(dictionaryDimensionFromQuery);
+ return getDictionaryMap(dictionaryColumnIdList, absoluteTableIdentifier);
+ }
+
+ /**
+ * Below method will be used to get the column id to its dictionary mapping
+ *
+ * @param dictionaryColumnIdList dictionary column list
+ * @param absoluteTableIdentifier absolute table identifier
+ * @return dictionary mapping
+ * @throws QueryExecutionException
+ */
+ private static Map<String, Dictionary> getDictionaryMap(List<String> dictionaryColumnIdList,
+ AbsoluteTableIdentifier absoluteTableIdentifier) throws QueryExecutionException {
+ // this for dictionary unique identifier
+ List<DictionaryColumnUniqueIdentifier> dictionaryColumnUniqueIdentifiers =
+ getDictionaryColumnUniqueIdentifierList(dictionaryColumnIdList,
+ absoluteTableIdentifier.getCarbonTableIdentifier());
+ CacheProvider cacheProvider = CacheProvider.getInstance();
+ Cache forwardDictionaryCache = cacheProvider
+ .createCache(CacheType.FORWARD_DICTIONARY, absoluteTableIdentifier.getStorePath());
+ List<Dictionary> columnDictionaryList = null;
+ try {
+ columnDictionaryList = forwardDictionaryCache.getAll(dictionaryColumnUniqueIdentifiers);
+ } catch (CarbonUtilException e) {
+ throw new QueryExecutionException(e);
+ }
+ Map<String, Dictionary> columnDictionaryMap = new HashMap<>(columnDictionaryList.size());
+ for (int i = 0; i < dictionaryColumnUniqueIdentifiers.size(); i++) {
+ // TODO: null check for column dictionary, if cache size is less it
+ // might return null here, in that case throw exception
+ columnDictionaryMap.put(dictionaryColumnIdList.get(i), columnDictionaryList.get(i));
+ }
+ return columnDictionaryMap;
+ }
+
+ /**
+ * Below method will be used to get the dictionary column unique identifier
+ *
+ * @param dictionaryColumnIdList dictionary
+ * @param carbonTableIdentifier
+ * @return
+ */
+ private static List<DictionaryColumnUniqueIdentifier> getDictionaryColumnUniqueIdentifierList(
- List<String> dictionaryColumnIdList, CarbonTableIdentifier carbonTableIdentifier) {
++ List<String> dictionaryColumnIdList, CarbonTableIdentifier carbonTableIdentifier)
++ throws QueryExecutionException {
+ CarbonTable carbonTable =
+ CarbonMetadata.getInstance().getCarbonTable(carbonTableIdentifier.getTableUniqueName());
+ List<DictionaryColumnUniqueIdentifier> dictionaryColumnUniqueIdentifiers =
+ new ArrayList<>(dictionaryColumnIdList.size());
- for (String columnIdentifier : dictionaryColumnIdList) {
++ for (String columnId : dictionaryColumnIdList) {
+ CarbonDimension dimension = CarbonMetadata.getInstance()
- .getCarbonDimensionBasedOnColIdentifier(carbonTable, columnIdentifier);
++ .getCarbonDimensionBasedOnColIdentifier(carbonTable, columnId);
++ if (null == dimension) {
++ throw new QueryExecutionException(
++ "The column id " + columnId + " could not be resolved.");
++ }
+ DictionaryColumnUniqueIdentifier dictionaryColumnUniqueIdentifier =
- new DictionaryColumnUniqueIdentifier(carbonTableIdentifier, columnIdentifier,
- dimension.getDataType());
++ new DictionaryColumnUniqueIdentifier(carbonTableIdentifier,
++ dimension.getColumnIdentifier(), dimension.getDataType());
+ dictionaryColumnUniqueIdentifiers.add(dictionaryColumnUniqueIdentifier);
+ }
+ return dictionaryColumnUniqueIdentifiers;
+ }
+
+ /**
+ * Below method will used to get the method will be used to get the measure
+ * block indexes to be read from the file
+ *
+ * @param queryMeasures query measure
+ * @param expressionMeasure measure present in the expression
+ * @param ordinalToBlockIndexMapping measure ordinal to block mapping
+ * @return block indexes
+ */
+ public static int[] getMeasureBlockIndexes(List<QueryMeasure> queryMeasures,
+ List<CarbonMeasure> expressionMeasure, Map<Integer, Integer> ordinalToBlockIndexMapping) {
+ Set<Integer> measureBlockIndex = new HashSet<Integer>();
+ for (int i = 0; i < queryMeasures.size(); i++) {
+ measureBlockIndex
+ .add(ordinalToBlockIndexMapping.get(queryMeasures.get(i).getMeasure().getOrdinal()));
+ }
+ for (int i = 0; i < expressionMeasure.size(); i++) {
+ measureBlockIndex.add(ordinalToBlockIndexMapping.get(expressionMeasure.get(i).getOrdinal()));
+ }
+ return ArrayUtils.toPrimitive(measureBlockIndex.toArray(new Integer[measureBlockIndex.size()]));
+ }
+
+ /**
+ * Below method will be used to get the masked byte range for dimension
+ * which is present in order by
+ *
+ * @param orderByDimensions order by dimension
+ * @param generator key generator
+ * @param maskedRanges masked byte range for dimension
+ * @return range of masked byte for order by dimension
+ */
+ public static int[][] getMaskedByteRangeForSorting(List<QueryDimension> orderByDimensions,
+ KeyGenerator generator, int[] maskedRanges) {
+ int[][] dimensionCompareIndex = new int[orderByDimensions.size()][];
+ int index = 0;
+ for (int i = 0; i < dimensionCompareIndex.length; i++) {
+ Set<Integer> integers = new TreeSet<Integer>();
+ if (!orderByDimensions.get(i).getDimension().getEncoder().contains(Encoding.DICTIONARY)
+ || orderByDimensions.get(i).getDimension().numberOfChild() > 0) {
+ continue;
+ }
+ int[] range =
+ generator.getKeyByteOffsets(orderByDimensions.get(i).getDimension().getKeyOrdinal());
+ for (int j = range[0]; j <= range[1]; j++) {
+ integers.add(j);
+ }
+ dimensionCompareIndex[index] = new int[integers.size()];
+ int j = 0;
+ for (Iterator<Integer> iterator = integers.iterator(); iterator.hasNext(); ) {
+ Integer integer = (Integer) iterator.next();
+ dimensionCompareIndex[index][j++] = integer.intValue();
+ }
+ index++;
+ }
+ for (int i = 0; i < dimensionCompareIndex.length; i++) {
+ if (null == dimensionCompareIndex[i]) {
+ continue;
+ }
+ int[] range = dimensionCompareIndex[i];
+ if (null != range) {
+ for (int j = 0; j < range.length; j++) {
+ for (int k = 0; k < maskedRanges.length; k++) {
+ if (range[j] == maskedRanges[k]) {
+ range[j] = k;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+ return dimensionCompareIndex;
+ }
+
+ /**
+ * Below method will be used to get the masked key for sorting
+ *
+ * @param orderDimensions query dimension
+ * @param generator key generator
+ * @param maskedByteRangeForSorting masked byte range for sorting
+ * @param maskedRanges masked range
+ * @return masked byte range
+ * @throws QueryExecutionException
+ */
+ public static byte[][] getMaksedKeyForSorting(List<QueryDimension> orderDimensions,
+ KeyGenerator generator, int[][] maskedByteRangeForSorting, int[] maskedRanges)
+ throws QueryExecutionException {
+ byte[][] maskedKey = new byte[orderDimensions.size()][];
+ byte[] mdKey = null;
+ long[] key = null;
+ byte[] maskedMdKey = null;
+ try {
+ if (null != maskedByteRangeForSorting) {
+ for (int i = 0; i < maskedByteRangeForSorting.length; i++) {
+ if (null == maskedByteRangeForSorting[i]) {
+ continue;
+ }
+ key = new long[generator.getDimCount()];
+ maskedKey[i] = new byte[maskedByteRangeForSorting[i].length];
+ key[orderDimensions.get(i).getDimension().getKeyOrdinal()] = Long.MAX_VALUE;
+ mdKey = generator.generateKey(key);
+ maskedMdKey = new byte[maskedRanges.length];
+ for (int k = 0; k < maskedMdKey.length; k++) { // CHECKSTYLE:OFF
+ // Approval
+ // No:Approval-V1R2C10_001
+ maskedMdKey[k] = mdKey[maskedRanges[k]];
+ }
+ for (int j = 0; j < maskedByteRangeForSorting[i].length; j++) {
+ maskedKey[i][j] = maskedMdKey[maskedByteRangeForSorting[i][j]];
+ }// CHECKSTYLE:ON
+
+ }
+ }
+ } catch (KeyGenException e) {
+ throw new QueryExecutionException(e);
+ }
+ return maskedKey;
+ }
+
+ /**
+ * Below method will be used to get mapping whether dimension is present in
+ * order by or not
+ *
+ * @param sortedDimensions sort dimension present in order by query
+ * @param queryDimensions query dimension
+ * @return sort dimension indexes
+ */
+ public static byte[] getSortDimensionIndexes(List<QueryDimension> sortedDimensions,
+ List<QueryDimension> queryDimensions) {
+ byte[] sortedDims = new byte[queryDimensions.size()];
+ int indexOf = 0;
+ for (int i = 0; i < sortedDims.length; i++) {
+ indexOf = sortedDimensions.indexOf(queryDimensions.get(i));
+ if (indexOf > -1) {
+ sortedDims[i] = 1;
+ }
+ }
+ return sortedDims;
+ }
+
+ /**
+ * Below method will be used to get the mapping of block index and its
+ * restructuring info
+ *
+ * @param queryDimensions query dimension from query model
+ * @param segmentProperties segment properties
+ * @return map of block index to its restructuring info
+ * @throws KeyGenException if problem while key generation
+ */
+ public static Map<Integer, KeyStructureInfo> getColumnGroupKeyStructureInfo(
+ List<QueryDimension> queryDimensions, SegmentProperties segmentProperties)
+ throws KeyGenException {
+ Map<Integer, KeyStructureInfo> rowGroupToItsRSInfo = new HashMap<Integer, KeyStructureInfo>();
+ // get column group id and its ordinal mapping of column group
+ Map<Integer, List<Integer>> columnGroupAndItsOrdinalMappingForQuery =
+ getColumnGroupAndItsOrdinalMapping(queryDimensions);
- KeyGenerator keyGenerator = segmentProperties.getDimensionKeyGenerator();
++ Map<Integer, KeyGenerator> columnGroupAndItsKeygenartor =
++ segmentProperties.getColumnGroupAndItsKeygenartor();
+
+ Iterator<Entry<Integer, List<Integer>>> iterator =
+ columnGroupAndItsOrdinalMappingForQuery.entrySet().iterator();
+ KeyStructureInfo restructureInfos = null;
+ while (iterator.hasNext()) {
+ Entry<Integer, List<Integer>> next = iterator.next();
++ KeyGenerator keyGenerator = columnGroupAndItsKeygenartor.get(next.getKey());
+ restructureInfos = new KeyStructureInfo();
+ // sort the ordinal
+ List<Integer> ordinal = next.getValue();
- Collections.sort(ordinal);
++ List<Integer> mdKeyOrdinal = new ArrayList<Integer>();
++ for (Integer ord : ordinal) {
++ mdKeyOrdinal.add(segmentProperties.getColumnGroupMdKeyOrdinal(next.getKey(), ord));
++ }
++ Collections.sort(mdKeyOrdinal);
+ // get the masked byte range for column group
- int[] maskByteRanges = getMaskedByteRangeBasedOrdinal(ordinal, keyGenerator);
++ int[] maskByteRanges = getMaskedByteRangeBasedOrdinal(mdKeyOrdinal, keyGenerator);
+ // max key for column group
- byte[] maxKey = getMaxKeyBasedOnOrinal(ordinal, keyGenerator);
++ byte[] maxKey = getMaxKeyBasedOnOrinal(mdKeyOrdinal, keyGenerator);
+ // get masked key for column group
+ int[] maksedByte = getMaskedByte(keyGenerator.getKeySizeInBytes(), maskByteRanges);
+ restructureInfos.setKeyGenerator(keyGenerator);
+ restructureInfos.setMaskByteRanges(maskByteRanges);
+ restructureInfos.setMaxKey(maxKey);
+ restructureInfos.setMaskedBytes(maksedByte);
- restructureInfos
- .setBlockMdKeyStartOffset(getBlockMdKeyStartOffset(segmentProperties, ordinal));
+ rowGroupToItsRSInfo
+ .put(segmentProperties.getDimensionOrdinalToBlockMapping().get(ordinal.get(0)),
+ restructureInfos);
+ }
+ return rowGroupToItsRSInfo;
+ }
+
+ /**
- * It return mdkey start index of given column group
- * @param segmentProperties
- * @param ordinal : column group ordinal
- * @return
- */
- public static int getBlockMdKeyStartOffset(SegmentProperties segmentProperties,
- List<Integer> ordinal) {
- int[][] colGroups = segmentProperties.getColumnGroups();
- int blockMdkeyStartOffset = 0;
- for (int i = 0; i < colGroups.length; i++) {
- if (QueryUtil.searchInArray(colGroups[i], ordinal.get(0))) {
- break;
- }
- blockMdkeyStartOffset += segmentProperties.getDimensionColumnsValueSize()[i];
- }
- return blockMdkeyStartOffset;
- }
-
- /**
+ * return true if given key is found in array
+ *
+ * @param data
+ * @param key
+ * @return
+ */
+ public static boolean searchInArray(int[] data, int key) {
+ for (int i = 0; i < data.length; i++) {
+ if (key == data[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Below method will be used to create a mapping of column group columns
+ * this mapping will have column group id to all the dimension ordinal
+ * present in the column group This mapping will be used during query
+ * execution, to create a mask key for the column group dimension which will
+ * be used in aggregation and filter query as column group dimension will be
+ * stored in bit level
+ */
+ private static Map<Integer, List<Integer>> getColumnGroupAndItsOrdinalMapping(
+ List<QueryDimension> origdimensions) {
+
+ List<QueryDimension> dimensions = new ArrayList<QueryDimension>(origdimensions.size());
+ dimensions.addAll(origdimensions);
+ /**
+ * sort based on column group id
+ */
+ Collections.sort(dimensions, new Comparator<QueryDimension>() {
+
+ @Override public int compare(QueryDimension o1, QueryDimension o2) {
+ return Integer
+ .compare(o1.getDimension().columnGroupId(), o2.getDimension().columnGroupId());
+ }
+ });
+ // list of row groups this will store all the row group column
+ Map<Integer, List<Integer>> columnGroupAndItsOrdinalsMapping =
+ new HashMap<Integer, List<Integer>>();
+ // to store a column group
+ List<Integer> currentColumnGroup = null;
+ // current index
+ int index = 0;
+ // previous column group to check all the column of row id has bee
+ // selected
+ int prvColumnGroupId = -1;
+ while (index < dimensions.size()) {
+ // if dimension group id is not zero and it is same as the previous
+ // column group id
+ // then we need to add ordinal of that column as it belongs to same
+ // column group
+ if (!dimensions.get(index).getDimension().isColumnar()
- && dimensions.get(index).getDimension().columnGroupId() == prvColumnGroupId) {
++ && dimensions.get(index).getDimension().columnGroupId() == prvColumnGroupId
++ && null != currentColumnGroup) {
+ currentColumnGroup.add(dimensions.get(index).getDimension().getOrdinal());
+ }
+
+ // if dimension is not a columnar then it is column group column
+ else if (!dimensions.get(index).getDimension().isColumnar()) {
+ currentColumnGroup = new ArrayList<Integer>();
+ columnGroupAndItsOrdinalsMapping
+ .put(dimensions.get(index).getDimension().columnGroupId(), currentColumnGroup);
+ currentColumnGroup.add(dimensions.get(index).getDimension().getOrdinal());
+ }
+ // update the row id every time,this is required to group the
+ // columns
+ // of the same row group
+ prvColumnGroupId = dimensions.get(index).getDimension().columnGroupId();
+ index++;
+ }
+ return columnGroupAndItsOrdinalsMapping;
+ }
+
+ /**
+ * Below method will be used to get masked byte
+ *
+ * @param data actual data
+ * @param maxKey max key
+ * @param maskByteRanges mask byte range
+ * @param byteCount
+ * @return masked byte
+ */
+ public static byte[] getMaskedKey(byte[] data, byte[] maxKey, int[] maskByteRanges,
+ int byteCount) {
+ byte[] maskedKey = new byte[byteCount];
+ int counter = 0;
+ int byteRange = 0;
+ for (int i = 0; i < byteCount; i++) {
+ byteRange = maskByteRanges[i];
+ if (byteRange != -1) {
+ maskedKey[counter++] = (byte) (data[byteRange] & maxKey[byteRange]);
+ }
+ }
+ return maskedKey;
+ }
+
+ /**
+ * Below method will be used to fill block indexes of the query dimension
+ * which will be used in creating a output row Here is method we are passing
+ * two list which store the indexes one for dictionary column other for not
+ * dictionary column. This is done for specific purpose so that in one
+ * iteration we will be able to fill both type dimension block indexes
+ *
+ * @param queryDimensions dimension present in the query
+ * @param columnOrdinalToBlockIndexMapping column ordinal to block index mapping
+ * @param dictionaryDimensionBlockIndex list to store dictionary column block indexes
+ * @param noDictionaryDimensionBlockIndex list to store no dictionary block indexes
+ */
+ public static void fillQueryDimensionsBlockIndexes(List<QueryDimension> queryDimensions,
+ Map<Integer, Integer> columnOrdinalToBlockIndexMapping,
+ Set<Integer> dictionaryDimensionBlockIndex, List<Integer> noDictionaryDimensionBlockIndex) {
+ for (QueryDimension queryDimension : queryDimensions) {
+ if (CarbonUtil.hasEncoding(queryDimension.getDimension().getEncoder(), Encoding.DICTIONARY)) {
+ dictionaryDimensionBlockIndex
+ .add(columnOrdinalToBlockIndexMapping.get(queryDimension.getDimension().getOrdinal()));
+ } else {
+ noDictionaryDimensionBlockIndex
+ .add(columnOrdinalToBlockIndexMapping.get(queryDimension.getDimension().getOrdinal()));
+ }
+ }
+ }
+
+ /**
+ * Below method will be used to resolve the query model
+ * resolve will be setting the actual dimension and measure object
+ * as from driver only column name will be passes to avoid the heavy object
+ * serialization
+ *
+ * @param queryModel query model
+ */
+ public static void resolveQueryModel(QueryModel queryModel) {
+ CarbonMetadata.getInstance().addCarbonTable(queryModel.getTable());
+ // TODO need to load the table from table identifier
+ CarbonTable carbonTable = queryModel.getTable();
+ String tableName =
+ queryModel.getAbsoluteTableIdentifier().getCarbonTableIdentifier().getTableName();
+ // resolve query dimension
+ for (QueryDimension queryDimension : queryModel.getQueryDimension()) {
+ queryDimension
+ .setDimension(carbonTable.getDimensionByName(tableName, queryDimension.getColumnName()));
+ }
+ // resolve sort dimension
+ for (QueryDimension sortDimension : queryModel.getSortDimension()) {
+ sortDimension
+ .setDimension(carbonTable.getDimensionByName(tableName, sortDimension.getColumnName()));
+ }
+ // resolve query measure
+ for (QueryMeasure queryMeasure : queryModel.getQueryMeasures()) {
+ // in case of count start column name will be count * so
- // for count start add first measure if measure is not present
++ // first need to check any measure is present or not and as if measure
++ // if measure is present and if first measure is not a default
++ // measure than add measure otherwise
+ // than add first dimension as a measure
++ //as currently if measure is not present then
++ //we are adding default measure so first condition will
++ //never come false but if in future we can remove so not removing first if check
+ if (queryMeasure.getColumnName().equals("count(*)")) {
- if (carbonTable.getMeasureByTableName(tableName).size() > 0) {
++ if (carbonTable.getMeasureByTableName(tableName).size() > 0 && !carbonTable
++ .getMeasureByTableName(tableName).get(0).getColName()
++ .equals(CarbonCommonConstants.DEFAULT_INVISIBLE_DUMMY_MEASURE)) {
+ queryMeasure.setMeasure(carbonTable.getMeasureByTableName(tableName).get(0));
+ } else {
+ CarbonMeasure dummyMeasure = new CarbonMeasure(
+ carbonTable.getDimensionByTableName(tableName).get(0).getColumnSchema(), 0);
+ queryMeasure.setMeasure(dummyMeasure);
+ }
+ } else {
+ queryMeasure
+ .setMeasure(carbonTable.getMeasureByName(tableName, queryMeasure.getColumnName()));
+ }
+ }
- //TODO need to handle expression
+ }
+
+ /**
+ * Below method will be used to get the index of number type aggregator
+ *
+ * @param aggType
+ * @return index in aggregator
+ */
+ public static int[] getNumberTypeIndex(List<String> aggType) {
+ List<Integer> indexList = new ArrayList<Integer>();
+ for (int i = 0; i < aggType.size(); i++) {
+ if (CarbonCommonConstants.SUM.equals(aggType.get(i)) || CarbonCommonConstants.AVERAGE
+ .equals(aggType.get(i))) {
+ indexList.add(i);
+ }
+ }
+ return ArrayUtils.toPrimitive(indexList.toArray(new Integer[indexList.size()]));
+ }
+
+ /**
+ * below method will be used to get the actual type aggregator
+ *
+ * @param aggType
+ * @return index in aggrgetor
+ */
+ public static int[] getActualTypeIndex(List<String> aggType) {
+ List<Integer> indexList = new ArrayList<Integer>();
+ for (int i = 0; i < aggType.size(); i++) {
+ if (!CarbonCommonConstants.SUM.equals(aggType.get(i)) && !CarbonCommonConstants.AVERAGE
+ .equals(aggType.get(i))) {
+ indexList.add(i);
+ }
+ }
+ return ArrayUtils.toPrimitive(indexList.toArray(new Integer[indexList.size()]));
+ }
++
++ /**
++ * It is required for extracting column data from columngroup chunk
++ *
++ * @return
++ * @throws KeyGenException
++ */
++ public static KeyStructureInfo getKeyStructureInfo(SegmentProperties segmentProperties,
++ DimColumnResolvedFilterInfo dimColumnEvaluatorInfo) throws KeyGenException {
++ int colGrpId = getColumnGroupId(segmentProperties, dimColumnEvaluatorInfo.getColumnIndex());
++ KeyGenerator keyGenerator = segmentProperties.getColumnGroupAndItsKeygenartor().get(colGrpId);
++ List<Integer> mdKeyOrdinal = new ArrayList<Integer>();
++
++ mdKeyOrdinal.add(segmentProperties
++ .getColumnGroupMdKeyOrdinal(colGrpId, dimColumnEvaluatorInfo.getColumnIndex()));
++ int[] maskByteRanges = QueryUtil.getMaskedByteRangeBasedOrdinal(mdKeyOrdinal, keyGenerator);
++ byte[] maxKey = QueryUtil.getMaxKeyBasedOnOrinal(mdKeyOrdinal, keyGenerator);
++ int[] maksedByte = QueryUtil.getMaskedByte(keyGenerator.getKeySizeInBytes(), maskByteRanges);
++ KeyStructureInfo restructureInfos = new KeyStructureInfo();
++ restructureInfos.setKeyGenerator(keyGenerator);
++ restructureInfos.setMaskByteRanges(maskByteRanges);
++ restructureInfos.setMaxKey(maxKey);
++ restructureInfos.setMaskedBytes(maksedByte);
++ return restructureInfos;
++ }
++
++ public static int getColumnGroupId(SegmentProperties segmentProperties, int ordinal) {
++ int[][] columnGroups = segmentProperties.getColumnGroups();
++ int colGrpId = -1;
++ for (int i = 0; i < columnGroups.length; i++) {
++ if (columnGroups[i].length > 1) {
++ colGrpId++;
++ if (QueryUtil.searchInArray(columnGroups[i], ordinal)) {
++ break;
++ }
++ }
++ }
++ return colGrpId;
++ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/ColumnExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/ColumnExpression.java
index 922e706,0000000..3807d29
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/ColumnExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/ColumnExpression.java
@@@ -1,112 -1,0 +1,113 @@@
+/*
+ * 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.carbondata.scan.expression;
+
+import org.carbondata.core.carbon.metadata.schema.table.column.CarbonColumn;
+import org.carbondata.core.carbon.metadata.schema.table.column.CarbonDimension;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class ColumnExpression extends LeafExpression {
+
+ private static final long serialVersionUID = 1L;
+
+ private String columnName;
+
+ private boolean isDimension;
+
+ private int colIndex = -1;
+
+ private DataType dataType;
+
+ private CarbonDimension dimension;
+
+ private CarbonColumn carbonColumn;
+
+ public ColumnExpression(String columnName, DataType dataType) {
+ this.columnName = columnName;
+ this.dataType = dataType;
+
+ }
+
+ public CarbonDimension getDimension() {
+ return dimension;
+ }
+
+ public void setDimension(CarbonDimension dimension) {
+ this.dimension = dimension;
+ }
+
+ public String getColumnName() {
+ return columnName;
+ }
+
+ public void setColumnName(String columnName) {
+ this.columnName = columnName;
+ }
+
+ public boolean isDimension() {
+ return isDimension;
+ }
+
+ public void setDimension(boolean isDimension) {
+ this.isDimension = isDimension;
+ }
+
+ public int getColIndex() {
+ return colIndex;
+ }
+
+ public void setColIndex(int colIndex) {
+ this.colIndex = colIndex;
+ }
+
+ public DataType getDataType() {
+ return dataType;
+ }
+
+ public void setDataType(DataType dataType) {
+ this.dataType = dataType;
+ }
+
+ @Override public ExpressionResult evaluate(RowIntf value) {
- ExpressionResult expressionResult = new ExpressionResult(dataType, value.getVal(colIndex));
++ ExpressionResult expressionResult =
++ new ExpressionResult(dataType, (null == value ? null : value.getVal(colIndex)));
+ return expressionResult;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override public String getString() {
+ // TODO Auto-generated method stub
+ return "ColumnExpression(" + columnName + ')';
+ }
+
+ public CarbonColumn getCarbonColumn() {
+ return carbonColumn;
+ }
+
+ public void setCarbonColumn(CarbonColumn carbonColumn) {
+ this.carbonColumn = carbonColumn;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/Expression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/Expression.java
index 01b4fee,0000000..31af903
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/Expression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/Expression.java
@@@ -1,48 -1,0 +1,50 @@@
+/*
+ * 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.carbondata.scan.expression;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.carbondata.core.constants.CarbonCommonConstants;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public abstract class Expression implements Serializable {
+
+ private static final long serialVersionUID = -7568676723039530713L;
+ protected List<Expression> children =
+ new ArrayList<Expression>(CarbonCommonConstants.DEFAULT_COLLECTION_SIZE);
+
- public abstract ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException;
++ public abstract ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException;
+
+ public abstract ExpressionType getFilterExpressionType();
+
+ public List<Expression> getChildren() {
+ return children;
+ }
+
+ public abstract String getString();
+
+ // public abstract void accept(ExpressionVisitor visitor);
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/ExpressionResult.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/ExpressionResult.java
index a86052c,0000000..63afabd
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/ExpressionResult.java
+++ b/core/src/main/java/org/carbondata/scan/expression/ExpressionResult.java
@@@ -1,466 -1,0 +1,474 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additiona l 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.carbondata.scan.expression;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.carbondata.core.constants.CarbonCommonConstants;
+import org.carbondata.core.util.CarbonProperties;
- import org.carbondata.scan.expression.exception.FilterUnsupportedException;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+
+public class ExpressionResult implements Comparable<ExpressionResult> {
+
+ private static final long serialVersionUID = 1L;
+ protected DataType dataType;
+
+ protected Object value;
+
+ private List<ExpressionResult> expressionResults;
+
+ public ExpressionResult(DataType dataType, Object value) {
+ this.dataType = dataType;
+ this.value = value;
+ }
+
+ public ExpressionResult(List<ExpressionResult> expressionResults) {
+ this.expressionResults = expressionResults;
+ }
+
+ public void set(DataType dataType, Object value) {
+ this.dataType = dataType;
+ this.value = value;
+ this.expressionResults = null;
+ }
+
+ public DataType getDataType() {
+ return dataType;
+ }
+
+ //CHECKSTYLE:OFF Approval No:Approval-V1R2C10_009
- public Integer getInt() throws FilterUnsupportedException {
++ public Integer getInt() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ try {
+ return Integer.parseInt(value.toString());
+ } catch (NumberFormatException e) {
- throw new FilterUnsupportedException(e);
++ throw new FilterIllegalMemberException(e);
+ }
+
+ case ShortType:
+ return ((Short) value).intValue();
+ case IntegerType:
+ case DoubleType:
+
+ if (value instanceof Double) {
+ return ((Double) value).intValue();
+ }
+ return (Integer) value;
+
+ case TimestampType:
+
+ if (value instanceof Timestamp) {
+ return (int) (((Timestamp) value).getTime() % 1000);
+ } else {
+ return (Integer) value;
+ }
+
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to integer type value");
+ }
+
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Integer type value");
+ }
+ }
+
- public Short getShort() throws FilterUnsupportedException {
++ public Short getShort() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ try {
+ return Short.parseShort(value.toString());
+ } catch (NumberFormatException e) {
- throw new FilterUnsupportedException(e);
++ throw new FilterIllegalMemberException(e);
+ }
+ case ShortType:
+ case IntegerType:
+ case DoubleType:
+
+ if (value instanceof Double) {
+ return ((Double) value).shortValue();
+ } else if (value instanceof Integer) {
+ return ((Integer) value).shortValue();
+ }
+ return (Short) value;
+
+ case TimestampType:
+
+ if (value instanceof Timestamp) {
+ return (short) (((Timestamp) value).getTime() % 1000);
+ } else {
+ return (Short) value;
+ }
+
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to integer type value");
+ }
+
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Integer type value");
+ }
+ }
+
- public String getString() {
++ public String getString() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
- switch (this.getDataType()) {
- case TimestampType:
- SimpleDateFormat parser = new SimpleDateFormat(CarbonProperties.getInstance()
- .getProperty(CarbonCommonConstants.CARBON_TIMESTAMP_FORMAT,
- CarbonCommonConstants.CARBON_TIMESTAMP_DEFAULT_FORMAT));
- if (value instanceof Timestamp) {
- return parser.format((Timestamp) value);
- } else {
- return parser.format(new Timestamp((long) value / 1000));
- }
-
- default:
- return value.toString();
++ try {
++ switch (this.getDataType()) {
++ case TimestampType:
++ SimpleDateFormat parser = new SimpleDateFormat(CarbonProperties.getInstance()
++ .getProperty(CarbonCommonConstants.CARBON_TIMESTAMP_FORMAT,
++ CarbonCommonConstants.CARBON_TIMESTAMP_DEFAULT_FORMAT));
++ if (value instanceof Timestamp) {
++ return parser.format((Timestamp) value);
++ } else {
++ return parser.format(new Timestamp((long) value / 1000));
++ }
++
++ default:
++ return value.toString();
++ }
++ } catch (Exception e) {
++ throw new FilterIllegalMemberException(
++ "Cannot convert" + this.getDataType().name() + " to String type value");
+ }
+ }
+
- public Double getDouble() throws FilterUnsupportedException {
++ public Double getDouble() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ try {
+ return Double.parseDouble(value.toString());
+ } catch (NumberFormatException e) {
- throw new FilterUnsupportedException(e);
++ throw new FilterIllegalMemberException(e);
+ }
+ case ShortType:
+ return ((Short) value).doubleValue();
+ case IntegerType:
+ return ((Integer) value).doubleValue();
+ case LongType:
+ return ((Long) value).doubleValue();
+ case DoubleType:
+ return (Double) value;
+ case TimestampType:
+ if (value instanceof Timestamp) {
+ return (double) ((Timestamp) value).getTime() * 1000;
+ } else {
+ return (Double) (value);
+ }
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to double type value");
+ }
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Double type value");
+ }
+ }
+ //CHECKSTYLE:ON
+
- public Long getLong() throws FilterUnsupportedException {
++ public Long getLong() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ try {
+ return Long.parseLong(value.toString());
+ } catch (NumberFormatException e) {
- throw new FilterUnsupportedException(e);
++ throw new FilterIllegalMemberException(e);
+ }
+ case ShortType:
+ return ((Short) value).longValue();
+ case IntegerType:
+ return (Long) value;
+ case LongType:
+ return (Long) value;
+ case DoubleType:
+ return (Long) value;
+ case TimestampType:
+ if (value instanceof Timestamp) {
+ return 1000 * ((Timestamp) value).getTime();
+ } else {
+ return (Long) value;
+ }
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Long type value");
+ }
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Long type value");
+ }
+
+ }
+
+ //Add to judge for BigDecimal
- public BigDecimal getDecimal() throws FilterUnsupportedException {
++ public BigDecimal getDecimal() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ try {
+ return new BigDecimal(value.toString());
+ } catch (NumberFormatException e) {
- throw new FilterUnsupportedException(e);
++ throw new FilterIllegalMemberException(e);
+ }
+ case ShortType:
+ return new BigDecimal((short) value);
+ case IntegerType:
+ return new BigDecimal((int) value);
+ case LongType:
+ return new BigDecimal((long) value);
+ case DoubleType:
+ return new BigDecimal((double) value);
+ case DecimalType:
+ return new BigDecimal(value.toString());
+ case TimestampType:
+ if (value instanceof Timestamp) {
+ return new BigDecimal(1000 * ((Timestamp) value).getTime());
+ } else {
+ return new BigDecimal((long) value);
+ }
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Long type value");
+ }
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Long type value");
+ }
+
+ }
+
- public Long getTime() throws FilterUnsupportedException {
++ public Long getTime() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
- SimpleDateFormat parser = new SimpleDateFormat(CarbonProperties.getInstance()
- .getProperty(CarbonCommonConstants.CARBON_TIMESTAMP_FORMAT,
- CarbonCommonConstants.CARBON_TIMESTAMP_DEFAULT_FORMAT));
++ // Currently the query engine layer only supports yyyy-MM-dd HH:mm:ss date format
++ // no matter in which format the data is been stored, so while retrieving the direct
++ // surrogate value for filter member first it should be converted in date form as per
++ // above format and needs to retrieve time stamp.
++ SimpleDateFormat parser =
++ new SimpleDateFormat(CarbonCommonConstants.CARBON_TIMESTAMP_DEFAULT_FORMAT);
+ Date dateToStr;
+ try {
+ dateToStr = parser.parse(value.toString());
+ return dateToStr.getTime() * 1000;
+ } catch (ParseException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Time/Long type value");
+ }
+ case ShortType:
+ return ((Short) value).longValue();
+ case IntegerType:
+ case LongType:
+ return (Long) value;
+ case DoubleType:
+ return (Long) value;
+ case TimestampType:
+ if (value instanceof Timestamp) {
+ return ((Timestamp) value).getTime() * 1000;
+ } else {
+ return (Long) value;
+ }
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Time/Long type value");
+ }
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Time/Long type value");
+ }
+
+ }
+
- public Boolean getBoolean() throws FilterUnsupportedException {
++ public Boolean getBoolean() throws FilterIllegalMemberException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ try {
+ return Boolean.parseBoolean(value.toString());
+ } catch (NumberFormatException e) {
- throw new FilterUnsupportedException(e);
++ throw new FilterIllegalMemberException(e);
+ }
+
+ case BooleanType:
+ return Boolean.parseBoolean(value.toString());
+
+ default:
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to boolean type value");
+ }
+ } catch (ClassCastException e) {
- throw new FilterUnsupportedException(
++ throw new FilterIllegalMemberException(
+ "Cannot convert" + this.getDataType().name() + " to Boolean type value");
+ }
+ }
+
+ public List<ExpressionResult> getList() {
+ if (null == expressionResults) {
+ List<ExpressionResult> a = new ArrayList<ExpressionResult>(20);
+ a.add(new ExpressionResult(dataType, value));
+ return a;
+ } else {
+ return expressionResults;
+ }
+ }
+
- public List<String> getListAsString() {
++ public List<String> getListAsString() throws FilterIllegalMemberException {
+ List<String> evaluateResultListFinal = new ArrayList<String>(20);
+ List<ExpressionResult> evaluateResultList = getList();
+ for (ExpressionResult result : evaluateResultList) {
+ if (result.getString() == null) {
+ evaluateResultListFinal.add(CarbonCommonConstants.MEMBER_DEFAULT_VAL);
+ continue;
+ }
+ evaluateResultListFinal.add(result.getString());
+ }
+ return evaluateResultListFinal;
+ }
+
+ @Override public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ if (null != expressionResults) {
+ result = prime * result + expressionResults.hashCode();
+ } else if (null != value) {
+ result = prime * result + value.toString().hashCode();
+ } else {
+ result = prime * result + "".hashCode();
+ }
+
+ return result;
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (!(obj instanceof ExpressionResult)) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ExpressionResult objToCompare = (ExpressionResult) obj;
+ boolean result = false;
+ if (this.value == objToCompare.value) {
+ return true;
+ }
+ try {
+ switch (this.getDataType()) {
+ case StringType:
+ result = this.getString().equals(objToCompare.getString());
+ break;
+ case ShortType:
+ result = this.getShort().equals(objToCompare.getShort());
+ break;
+ case IntegerType:
+ result = this.getInt().equals(objToCompare.getInt());
+ break;
+
+ case DoubleType:
+ result = this.getDouble().equals(objToCompare.getDouble());
+ break;
+ case TimestampType:
+ result = this.getLong().equals(objToCompare.getLong());
+ break;
+ default:
+ break;
+ }
- } catch (FilterUnsupportedException ex) {
++ } catch (FilterIllegalMemberException ex) {
+ return false;
+ }
+
+ return result;
+ }
+
+ public boolean isNull() {
+ return value == null;
+ }
+
+ @Override public int compareTo(ExpressionResult o) {
+ try {
+ switch (o.dataType) {
+ case ShortType:
+ case IntegerType:
+ case LongType:
+ case DoubleType:
+
+ Double d1 = this.getDouble();
+ Double d2 = o.getDouble();
+ return d1.compareTo(d2);
+ case DecimalType:
+ java.math.BigDecimal val1 = this.getDecimal();
+ java.math.BigDecimal val2 = o.getDecimal();
+ return val1.compareTo(val2);
+ case TimestampType:
+ SimpleDateFormat parser = new SimpleDateFormat(CarbonProperties.getInstance()
+ .getProperty(CarbonCommonConstants.CARBON_TIMESTAMP_FORMAT,
+ CarbonCommonConstants.CARBON_TIMESTAMP_DEFAULT_FORMAT));
+ Date date1 = null;
+ Date date2 = null;
+ date1 = parser.parse(this.getString());
+ date2 = parser.parse(o.getString());
+ return date1.compareTo(date2);
+ case StringType:
+ default:
+ return this.getString().compareTo(o.getString());
+ }
+ } catch (Exception e) {
+ return -1;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/arithmetic/AddExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/arithmetic/AddExpression.java
index 62bab78,0000000..5bc1373
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/arithmetic/AddExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/arithmetic/AddExpression.java
@@@ -1,84 -1,0 +1,86 @@@
+/*
+ * 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.carbondata.scan.expression.arithmetic;
+
+import org.carbondata.scan.expression.DataType;
+import org.carbondata.scan.expression.Expression;
+import org.carbondata.scan.expression.ExpressionResult;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class AddExpression extends BinaryArithmeticExpression {
+ private static final long serialVersionUID = 7999436055420911612L;
+
+ public AddExpression(Expression left, Expression right) {
+ super(left, right);
+ }
+
- @Override public ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException {
++ @Override public ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException {
+ ExpressionResult addExprLeftRes = left.evaluate(value);
+ ExpressionResult addExprRightRes = right.evaluate(value);
+ ExpressionResult val1 = addExprLeftRes;
+ ExpressionResult val2 = addExprRightRes;
+ if (addExprLeftRes.isNull() || addExprRightRes.isNull()) {
+ addExprLeftRes.set(addExprLeftRes.getDataType(), null);
+ return addExprLeftRes;
+ }
+
+ if (addExprLeftRes.getDataType() != addExprRightRes.getDataType()) {
+ if (addExprLeftRes.getDataType().getPresedenceOrder() < addExprRightRes.getDataType()
+ .getPresedenceOrder()) {
+ val2 = addExprLeftRes;
+ val1 = addExprRightRes;
+ }
+ }
+ switch (val1.getDataType()) {
+ case StringType:
+ case DoubleType:
+ addExprRightRes.set(DataType.DoubleType, val1.getDouble() + val2.getDouble());
+ break;
+ case ShortType:
+ addExprRightRes.set(DataType.ShortType, val1.getShort() + val2.getShort());
+ break;
+ case IntegerType:
+ addExprRightRes.set(DataType.IntegerType, val1.getInt() + val2.getInt());
+ break;
+ case LongType:
+ addExprRightRes.set(DataType.LongType, val1.getLong() + val2.getLong());
+ break;
+ case DecimalType:
+ addExprRightRes.set(DataType.DecimalType, val1.getDecimal().add(val2.getDecimal()));
+ break;
+ default:
+ throw new FilterUnsupportedException(
+ "Incompatible datatype for applying Add Expression Filter " + val1.getDataType());
+ }
+ return addExprRightRes;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ return ExpressionType.ADD;
+ }
+
+ @Override public String getString() {
+ return "Add(" + left.getString() + ',' + right.getString() + ',';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/arithmetic/DivideExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/arithmetic/DivideExpression.java
index d98b301,0000000..3e858e2
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/arithmetic/DivideExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/arithmetic/DivideExpression.java
@@@ -1,84 -1,0 +1,86 @@@
+/*
+ * 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.carbondata.scan.expression.arithmetic;
+
+import org.carbondata.scan.expression.DataType;
+import org.carbondata.scan.expression.Expression;
+import org.carbondata.scan.expression.ExpressionResult;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class DivideExpression extends BinaryArithmeticExpression {
+ private static final long serialVersionUID = -7269266926782365612L;
+
+ public DivideExpression(Expression left, Expression right) {
+ super(left, right);
+ }
+
- @Override public ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException {
++ @Override public ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException {
+ ExpressionResult divideExprLeftRes = left.evaluate(value);
+ ExpressionResult divideExprRightRes = right.evaluate(value);
+ ExpressionResult val1 = divideExprLeftRes;
+ ExpressionResult val2 = divideExprRightRes;
+ if (divideExprLeftRes.isNull() || divideExprRightRes.isNull()) {
+ divideExprLeftRes.set(divideExprLeftRes.getDataType(), null);
+ return divideExprLeftRes;
+ }
+ if (divideExprLeftRes.getDataType() != divideExprRightRes.getDataType()) {
+ if (divideExprLeftRes.getDataType().getPresedenceOrder() < divideExprRightRes.getDataType()
+ .getPresedenceOrder()) {
+ val2 = divideExprLeftRes;
+ val1 = divideExprRightRes;
+ }
+ }
+ switch (val1.getDataType()) {
+ case StringType:
+ case DoubleType:
+ divideExprRightRes.set(DataType.DoubleType, val1.getDouble() / val2.getDouble());
+ break;
+ case ShortType:
+ divideExprRightRes.set(DataType.ShortType, val1.getShort() / val2.getShort());
+ break;
+ case IntegerType:
+ divideExprRightRes.set(DataType.IntegerType, val1.getInt() / val2.getInt());
+ break;
+ case LongType:
+ divideExprRightRes.set(DataType.LongType, val1.getLong() / val2.getLong());
+ break;
+ case DecimalType:
+ divideExprRightRes.set(DataType.DecimalType, val1.getDecimal().divide(val2.getDecimal()));
+ break;
+ default:
+ throw new FilterUnsupportedException(
+ "Incompatible datatype for applying Add Expression Filter " + divideExprLeftRes
+ .getDataType());
+ }
+ return divideExprRightRes;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ return ExpressionType.DIVIDE;
+ }
+
+ @Override public String getString() {
+ return "Divide(" + left.getString() + ',' + right.getString() + ')';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/arithmetic/MultiplyExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/arithmetic/MultiplyExpression.java
index 7f8d8aa,0000000..72b45c7
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/arithmetic/MultiplyExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/arithmetic/MultiplyExpression.java
@@@ -1,86 -1,0 +1,88 @@@
+/*
+ * 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.carbondata.scan.expression.arithmetic;
+
+import org.carbondata.scan.expression.DataType;
+import org.carbondata.scan.expression.Expression;
+import org.carbondata.scan.expression.ExpressionResult;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class MultiplyExpression extends BinaryArithmeticExpression {
+ private static final long serialVersionUID = 1L;
+
+ public MultiplyExpression(Expression left, Expression right) {
+ super(left, right);
+ }
+
- @Override public ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException {
++ @Override public ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException {
+ ExpressionResult multiplyExprLeftRes = left.evaluate(value);
+ ExpressionResult multiplyExprRightRes = right.evaluate(value);
+ ExpressionResult val1 = multiplyExprLeftRes;
+ ExpressionResult val2 = multiplyExprRightRes;
+ if (multiplyExprLeftRes.isNull() || multiplyExprRightRes.isNull()) {
+ multiplyExprLeftRes.set(multiplyExprLeftRes.getDataType(), null);
+ return multiplyExprLeftRes;
+ }
+
+ if (multiplyExprLeftRes.getDataType() != multiplyExprRightRes.getDataType()) {
+ if (multiplyExprLeftRes.getDataType().getPresedenceOrder() < multiplyExprRightRes
+ .getDataType().getPresedenceOrder()) {
+ val2 = multiplyExprLeftRes;
+ val1 = multiplyExprRightRes;
+ }
+ }
+ switch (val1.getDataType()) {
+ case StringType:
+ case DoubleType:
+ multiplyExprRightRes.set(DataType.DoubleType, val1.getDouble() * val2.getDouble());
+ break;
+ case ShortType:
+ multiplyExprRightRes.set(DataType.ShortType, val1.getShort() * val2.getShort());
+ break;
+ case IntegerType:
+ multiplyExprRightRes.set(DataType.IntegerType, val1.getInt() * val2.getInt());
+ break;
+ case LongType:
+ multiplyExprRightRes.set(DataType.LongType, val1.getLong() * val2.getLong());
+ break;
+ case DecimalType:
+ multiplyExprRightRes
+ .set(DataType.DecimalType, val1.getDecimal().multiply(val2.getDecimal()));
+ break;
+ default:
+ throw new FilterUnsupportedException(
+ "Incompatible datatype for applying Add Expression Filter " + multiplyExprLeftRes
+ .getDataType());
+ }
+ return multiplyExprRightRes;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ return ExpressionType.MULTIPLY;
+ }
+
+ @Override public String getString() {
+ return "Substract(" + left.getString() + ',' + right.getString() + ')';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/arithmetic/SubstractExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/arithmetic/SubstractExpression.java
index 0e7ab2e,0000000..b65b032
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/arithmetic/SubstractExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/arithmetic/SubstractExpression.java
@@@ -1,86 -1,0 +1,88 @@@
+/*
+ * 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.carbondata.scan.expression.arithmetic;
+
+import org.carbondata.scan.expression.DataType;
+import org.carbondata.scan.expression.Expression;
+import org.carbondata.scan.expression.ExpressionResult;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class SubstractExpression extends BinaryArithmeticExpression {
+
+ private static final long serialVersionUID = -8304726440185363102L;
+
+ public SubstractExpression(Expression left, Expression right) {
+ super(left, right);
+ }
+
- @Override public ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException {
++ @Override public ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException {
+ ExpressionResult subtractExprLeftRes = left.evaluate(value);
+ ExpressionResult subtractExprRightRes = right.evaluate(value);
+ ExpressionResult val1 = subtractExprLeftRes;
+ ExpressionResult val2 = subtractExprRightRes;
+ if (subtractExprLeftRes.isNull() || subtractExprRightRes.isNull()) {
+ subtractExprLeftRes.set(subtractExprLeftRes.getDataType(), null);
+ return subtractExprLeftRes;
+ }
+ if (subtractExprLeftRes.getDataType() != subtractExprRightRes.getDataType()) {
+ if (subtractExprLeftRes.getDataType().getPresedenceOrder() < subtractExprRightRes
+ .getDataType().getPresedenceOrder()) {
+ val2 = subtractExprLeftRes;
+ val1 = subtractExprRightRes;
+ }
+ }
+ switch (val1.getDataType()) {
+ case StringType:
+ case DoubleType:
+ subtractExprRightRes.set(DataType.DoubleType, val1.getDouble() - val2.getDouble());
+ break;
+ case ShortType:
+ subtractExprRightRes.set(DataType.ShortType, val1.getShort() - val2.getShort());
+ break;
+ case IntegerType:
+ subtractExprRightRes.set(DataType.IntegerType, val1.getInt() - val2.getInt());
+ break;
+ case LongType:
+ subtractExprRightRes.set(DataType.LongType, val1.getLong() - val2.getLong());
+ break;
+ case DecimalType:
+ subtractExprRightRes
+ .set(DataType.DecimalType, val1.getDecimal().subtract(val2.getDecimal()));
+ break;
+ default:
+ throw new FilterUnsupportedException(
+ "Incompatible datatype for applying Add Expression Filter " + subtractExprLeftRes
+ .getDataType());
+ }
+ return subtractExprRightRes;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ return ExpressionType.SUBSTRACT;
+ }
+
+ @Override public String getString() {
+ return "Substract(" + left.getString() + ',' + right.getString() + ')';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/conditional/EqualToExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/conditional/EqualToExpression.java
index 80ad32e,0000000..ce8be43
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/conditional/EqualToExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/conditional/EqualToExpression.java
@@@ -1,98 -1,0 +1,99 @@@
+/*
+ * 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.carbondata.scan.expression.conditional;
+
+import org.carbondata.scan.expression.DataType;
+import org.carbondata.scan.expression.Expression;
+import org.carbondata.scan.expression.ExpressionResult;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class EqualToExpression extends BinaryConditionalExpression {
+
+ private static final long serialVersionUID = 1L;
+
+ public EqualToExpression(Expression left, Expression right) {
+ super(left, right);
+ }
+
- @Override public ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException {
++ @Override public ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException {
+ ExpressionResult elRes = left.evaluate(value);
+ ExpressionResult erRes = right.evaluate(value);
+
+ boolean result = false;
+
+ ExpressionResult val1 = elRes;
+ ExpressionResult val2 = erRes;
+
+ if (elRes.isNull() || erRes.isNull()) {
+ result = elRes.isNull() && erRes.isNull();
+ val1.set(DataType.BooleanType, result);
+ return val1;
+ }
+ //default implementation if the data types are different for the resultsets
+ if (elRes.getDataType() != erRes.getDataType()) {
+ if (elRes.getDataType().getPresedenceOrder() < erRes.getDataType().getPresedenceOrder()) {
+ val2 = elRes;
+ val1 = erRes;
+ }
+ }
+
- // todo: move to util
+ switch (val1.getDataType()) {
+ case StringType:
+ result = val1.getString().equals(val2.getString());
+ break;
+ case ShortType:
+ result = val1.getShort().equals(val2.getShort());
+ break;
+ case IntegerType:
+ result = val1.getInt().equals(val2.getInt());
+ break;
+ case DoubleType:
+ result = val1.getDouble().equals(val2.getDouble());
+ break;
+ case TimestampType:
+ result = val1.getTime().equals(val2.getTime());
+ break;
+ case LongType:
+ result = val1.getLong().equals(val2.getLong());
+ break;
+ case DecimalType:
+ result = val1.getDecimal().compareTo(val2.getDecimal()) == 0;
+ break;
+ default:
+ throw new FilterUnsupportedException(
+ "DataType: " + val1.getDataType() + " not supported for the filter expression");
+ }
+ val1.set(DataType.BooleanType, result);
+ return val1;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ return ExpressionType.EQUALS;
+ }
+
+ @Override public String getString() {
+ return "EqualTo(" + left.getString() + ',' + right.getString() + ')';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-carbondata/blob/7f722186/core/src/main/java/org/carbondata/scan/expression/conditional/GreaterThanEqualToExpression.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/carbondata/scan/expression/conditional/GreaterThanEqualToExpression.java
index 4da578b,0000000..5318408
mode 100644,000000..100644
--- a/core/src/main/java/org/carbondata/scan/expression/conditional/GreaterThanEqualToExpression.java
+++ b/core/src/main/java/org/carbondata/scan/expression/conditional/GreaterThanEqualToExpression.java
@@@ -1,88 -1,0 +1,90 @@@
+/*
+ * 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.carbondata.scan.expression.conditional;
+
+import org.carbondata.scan.expression.DataType;
+import org.carbondata.scan.expression.Expression;
+import org.carbondata.scan.expression.ExpressionResult;
++import org.carbondata.scan.expression.exception.FilterIllegalMemberException;
+import org.carbondata.scan.expression.exception.FilterUnsupportedException;
+import org.carbondata.scan.filter.intf.ExpressionType;
+import org.carbondata.scan.filter.intf.RowIntf;
+
+public class GreaterThanEqualToExpression extends BinaryConditionalExpression {
+ private static final long serialVersionUID = 4185317066280688984L;
+
+ public GreaterThanEqualToExpression(Expression left, Expression right) {
+ super(left, right);
+ }
+
- public ExpressionResult evaluate(RowIntf value) throws FilterUnsupportedException {
++ public ExpressionResult evaluate(RowIntf value)
++ throws FilterUnsupportedException, FilterIllegalMemberException {
+ ExpressionResult elRes = left.evaluate(value);
+ ExpressionResult erRes = right.evaluate(value);
+ ExpressionResult exprResVal1 = elRes;
+ if (elRes.isNull() || erRes.isNull()) {
+ elRes.set(DataType.BooleanType, false);
+ return elRes;
+ }
+ if (elRes.getDataType() != erRes.getDataType()) {
+ if (elRes.getDataType().getPresedenceOrder() < erRes.getDataType().getPresedenceOrder()) {
+ exprResVal1 = erRes;
+ }
+
+ }
+ boolean result = false;
+ switch (exprResVal1.getDataType()) {
+ case StringType:
+ result = elRes.getString().compareTo(erRes.getString()) >= 0;
+ break;
+ case ShortType:
+ result = elRes.getShort() >= (erRes.getShort());
+ break;
+ case IntegerType:
+ result = elRes.getInt() >= (erRes.getInt());
+ break;
+ case DoubleType:
+ result = elRes.getDouble() >= (erRes.getDouble());
+ break;
+ case TimestampType:
+ result = elRes.getTime() >= (erRes.getTime());
+ break;
+ case LongType:
+ result = elRes.getLong() >= (erRes.getLong());
+ break;
+ case DecimalType:
+ result = elRes.getDecimal().compareTo(erRes.getDecimal()) >= 0;
+ break;
+ default:
+ throw new FilterUnsupportedException(
+ "DataType: " + exprResVal1.getDataType() + " not supported for the filter expression");
+ }
+ exprResVal1.set(DataType.BooleanType, result);
+ return exprResVal1;
+ }
+
+ @Override public ExpressionType getFilterExpressionType() {
+ return ExpressionType.GREATERTHAN_EQUALTO;
+ }
+
+ @Override public String getString() {
+ return "GreaterThanEqualTo(" + left.getString() + ',' + right.getString() + ')';
+ }
+}