blob: 85f6aa0a5a5c24232fc036d77ff7fe220b66682a [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.flink.table.runtime.range;
import org.apache.flink.annotation.Internal;
import org.apache.flink.api.common.distributions.RangeBoundaries;
import org.apache.flink.api.common.typeutils.TypeComparator;
import org.apache.flink.table.dataformat.BaseRow;
/**
* split the records into multiple ranges.
*/
@Internal
public class CommonRangeBoundaries implements RangeBoundaries<BaseRow> {
private final KeyExtractor keyExtractor;
private final Object[][] boundaries;
private final TypeComparator[] flatComparators;
private final Object[] keys;
public CommonRangeBoundaries(KeyExtractor keyExtractor, Object[][] boundaries) {
this.keyExtractor = keyExtractor;
this.flatComparators = keyExtractor.getFlatComparators();
this.keys = new Object[flatComparators.length];
this.boundaries = boundaries;
}
@Override
public int getRangeIndex(BaseRow record) {
return binarySearch(record);
}
// Search the range index of input record.
private int binarySearch(BaseRow record) {
int low = 0;
int high = this.boundaries.length - 1;
keyExtractor.extractKeys(record, keys, 0);
while (low <= high) {
final int mid = (low + high) >>> 1;
final int result = compareKeys(flatComparators, keys, this.boundaries[mid]);
if (result > 0) {
low = mid + 1;
} else if (result < 0) {
high = mid - 1;
} else {
return mid;
}
}
// key not found, but the low index is the target
// bucket, since the boundaries are the upper bound
return low;
}
private int compareKeys(TypeComparator[] flatComparators, Object[] keys, Object[] boundary) {
if (flatComparators.length != keys.length || flatComparators.length != boundary.length) {
throw new RuntimeException("Can not compare keys with boundary due to mismatched length.");
}
for (int i = 0; i < flatComparators.length; i++) {
int result = flatComparators[i].compare(keys[i], boundary[i]);
if (result != 0) {
return result;
}
}
return 0;
}
}