blob: 3bd1fd7e3c98913c228066118f3deb31e172fd4a [file] [log] [blame]
/*
* 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.phoenix.filter;
import java.io.IOException;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Writables;
import org.apache.phoenix.expression.Expression;
/**
*
* Filter that evaluates WHERE clause expression, used in the case where there
* are references to multiple column qualifiers over multiple column families.
* Also there same qualifier names in different families.
*
*/
public class MultiCFCQKeyValueComparisonFilter extends MultiKeyValueComparisonFilter {
private final ImmutablePairBytesPtr ptr = new ImmutablePairBytesPtr();
public MultiCFCQKeyValueComparisonFilter() {
}
public MultiCFCQKeyValueComparisonFilter(Expression expression) {
super(expression);
}
@Override
protected Object setColumnKey(byte[] cf, int cfOffset, int cfLength,
byte[] cq, int cqOffset, int cqLength) {
ptr.set(cf, cfOffset, cfLength, cq, cqOffset, cqLength);
return ptr;
}
@Override
protected Object newColumnKey(byte[] cf, int cfOffset, int cfLength,
byte[] cq, int cqOffset, int cqLength) {
byte[] cfKey;
if (cfOffset == 0 && cf.length == cfLength) {
cfKey = cf;
} else {
// Copy bytes here, but figure cf names are typically a few bytes at most,
// so this will be better than creating an ImmutableBytesPtr
cfKey = new byte[cfLength];
System.arraycopy(cf, cfOffset, cfKey, 0, cfLength);
}
cfSet.add(cfKey);
return new ImmutablePairBytesPtr(cf, cfOffset, cfLength, cq, cqOffset, cqLength);
}
private static class ImmutablePairBytesPtr {
private byte[] bytes1;
private int offset1;
private int length1;
private byte[] bytes2;
private int offset2;
private int length2;
private int hashCode;
private ImmutablePairBytesPtr() {
}
private ImmutablePairBytesPtr(byte[] bytes1, int offset1, int length1, byte[] bytes2, int offset2, int length2) {
set(bytes1, offset1, length1, bytes2, offset2, length2);
}
@Override
public int hashCode() {
return hashCode;
}
public void set(byte[] bytes1, int offset1, int length1, byte[] bytes2, int offset2, int length2) {
this.bytes1 = bytes1;
this.offset1 = offset1;
this.length1 = length1;
this.bytes2 = bytes2;
this.offset2 = offset2;
this.length2 = length2;
int hash = 1;
for (int i = offset1; i < offset1 + length1; i++)
hash = (31 * hash) + bytes1[i];
for (int i = offset2; i < offset2 + length2; i++)
hash = (31 * hash) + bytes2[i];
hashCode = hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
ImmutablePairBytesPtr that = (ImmutablePairBytesPtr)obj;
if (this.hashCode != that.hashCode) return false;
if (Bytes.compareTo(this.bytes2, this.offset2, this.length2, that.bytes2, that.offset2, that.length2) != 0) return false;
if (Bytes.compareTo(this.bytes1, this.offset1, this.length1, that.bytes1, that.offset1, that.length1) != 0) return false;
return true;
}
}
public static MultiCFCQKeyValueComparisonFilter parseFrom(final byte [] pbBytes) throws DeserializationException {
try {
return (MultiCFCQKeyValueComparisonFilter)Writables.getWritable(pbBytes, new MultiCFCQKeyValueComparisonFilter());
} catch (IOException e) {
throw new DeserializationException(e);
}
}
}