/**
* 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.hadoop.hive.hbase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hive.hbase.ColumnMappings.ColumnMapping;
import org.apache.hadoop.hive.ql.index.IndexSearchCondition;
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
import org.apache.hadoop.hive.serde2.Deserializer;
import org.apache.hadoop.hive.serde2.typeinfo.StructTypeInfo;
import org.apache.hadoop.mapred.JobConf;
/**
* Simple extension of {@link SampleHBaseKeyFactory2} with exception of using filters instead of start
* and stop keys
* */
public class SampleHBaseKeyFactory3 extends SampleHBaseKeyFactory2 {
@Override
public DecomposedPredicate decomposePredicate(JobConf jobConf, Deserializer deserializer,
ExprNodeDesc predicate) {
SampleHBasePredicateDecomposer decomposedPredicate = new SampleHBasePredicateDecomposer(keyMapping);
return decomposedPredicate.decomposePredicate(keyMapping.columnName, predicate);
}
}
class SampleHBasePredicateDecomposer extends AbstractHBaseKeyPredicateDecomposer {
private static final int FIXED_LENGTH = 10;
private ColumnMapping keyMapping;
SampleHBasePredicateDecomposer(ColumnMapping keyMapping) {
this.keyMapping = keyMapping;
}
@Override
public HBaseScanRange getScanRange(List<IndexSearchCondition> searchConditions)
throws Exception {
Map<String, List<IndexSearchCondition>> fieldConds =
new HashMap<String, List<IndexSearchCondition>>();
for (IndexSearchCondition condition : searchConditions) {
String fieldName = condition.getFields()[0];
List<IndexSearchCondition> fieldCond = fieldConds.get(fieldName);
if (fieldCond == null) {
fieldConds.put(fieldName, fieldCond = new ArrayList<IndexSearchCondition>());
}
fieldCond.add(condition);
}
Filter filter = null;
HBaseScanRange range = new HBaseScanRange();
StructTypeInfo type = (StructTypeInfo) keyMapping.columnType;
for (String name : type.getAllStructFieldNames()) {
List<IndexSearchCondition> fieldCond = fieldConds.get(name);
if (fieldCond == null || fieldCond.size() > 2) {
continue;
}
for (IndexSearchCondition condition : fieldCond) {
if (condition.getConstantDesc().getValue() == null) {
continue;
}
String comparisonOp = condition.getComparisonOp();
String constantVal = String.valueOf(condition.getConstantDesc().getValue());
byte[] valueAsBytes = toBinary(constantVal, FIXED_LENGTH, false, false);
if (comparisonOp.endsWith("UDFOPEqual")) {
filter = new RowFilter(CompareOp.EQUAL, new BinaryComparator(valueAsBytes));
} else if (comparisonOp.endsWith("UDFOPEqualOrGreaterThan")) {
filter = new RowFilter(CompareOp.GREATER_OR_EQUAL, new BinaryComparator(valueAsBytes));
} else if (comparisonOp.endsWith("UDFOPGreaterThan")) {
filter = new RowFilter(CompareOp.GREATER, new BinaryComparator(valueAsBytes));
} else if (comparisonOp.endsWith("UDFOPEqualOrLessThan")) {
filter = new RowFilter(CompareOp.LESS_OR_EQUAL, new BinaryComparator(valueAsBytes));
} else if (comparisonOp.endsWith("UDFOPLessThan")) {
filter = new RowFilter(CompareOp.LESS, new BinaryComparator(valueAsBytes));
} else {
throw new IOException(comparisonOp + " is not a supported comparison operator");
}
}
}
if (filter != null) {
range.addFilter(filter);
}
return range;
}
private byte[] toBinary(String value, int max, boolean end, boolean nextBA) {
return toBinary(value.getBytes(), max, end, nextBA);
}
private byte[] toBinary(byte[] value, int max, boolean end, boolean nextBA) {
byte[] bytes = new byte[max + 1];
System.arraycopy(value, 0, bytes, 0, Math.min(value.length, max));
if (end) {
Arrays.fill(bytes, value.length, max, (byte) 0xff);
}
if (nextBA) {
bytes[max] = 0x01;
}
return bytes;
}
}