use of com.pingcap.tikv.key.TypedKey in project tispark by pingcap.
the class IndexRangeSetBuilder method visit.
@Override
protected RangeSet<TypedKey> visit(ComparisonBinaryExpression node, Void context) {
NormalizedPredicate predicate = node.normalize();
if (predicate == null) {
throwOnError(node);
}
// In order to match a prefix index, we have to cut the literal by prefix length.
// e.g., for table t:
// CREATE TABLE `t` {
// `b` VARCHAR(10) DEFAULT NULL,
// KEY `prefix_index` (`b`(2))
// }
//
// b(2) > "bbc" -> ["bb", +∞)
// b(2) >= "bbc" -> ["bb", +∞)
// b(2) < "bbc" -> (-∞, "bb"]
// b(2) <= "bbc" -> (-∞, "bb"]
// b(2) = "bbc" -> ["bb", "bb"]
// b(2) > "b" -> ["b", +∞)
// b(2) >= "b" -> ["b", +∞)
// b(2) < "b" -> (-∞, "b"]
// b(2) <= "b" -> (-∞, "b"]
//
// For varchar, `b`(2) will take first two characters(bytes) as prefix index.
// TODO: Note that TiDB only supports UTF-8, we need to check if prefix index behave differently
// under other encoding methods
int prefixLen = lengths.getOrDefault(predicate.getColumnRef(), DataType.UNSPECIFIED_LEN);
TypedKey literal = predicate.getTypedLiteral(prefixLen);
boolean loose = !DataType.isLengthUnSpecified(prefixLen);
// With prefix length specified, the filter is loosen and so should the ranges
return visitComparisonBinaryExpr(node, context, literal, loose);
}
use of com.pingcap.tikv.key.TypedKey in project tispark by pingcap.
the class PrunedPartitionBuilder method visit.
@Override
protected RangeSet<TypedKey> visit(ComparisonBinaryExpression node, Void context) {
NormalizedPredicate predicate = node.normalize();
// which indicates it cannot be pruned such as a > b + 1
if (predicate == null)
return TreeRangeSet.<TypedKey>create().complement();
if (!partExprColRefs.contains(predicate.getColumnRef()))
return TreeRangeSet.<TypedKey>create().complement();
TypedKey literal;
literal = predicate.getTypedLiteral(-1);
return visitComparisonBinaryExpr(node, context, literal, false);
}
use of com.pingcap.tikv.key.TypedKey in project tispark by pingcap.
the class RangePartitionPruner method pruneRangeNormalPart.
private List<TiPartitionDef> pruneRangeNormalPart(Expression cnfExpr) {
Objects.requireNonNull(cnfExpr, "cnf expression cannot be null at pruning stage");
// we need rewrite filter expression if partition expression is a Year expression.
// This step is designed to deal with y < '1995-10-10'(in filter condition and also a part of
// partition expression) where y is a date type.
// Rewriting only applies partition expression on the constant part, resulting year(y) < 1995.
PartAndFilterExprRewriter expressionRewriter = new PartAndFilterExprRewriter(partExpr);
cnfExpr = expressionRewriter.rewrite(cnfExpr);
// if we find an unsupported partition function, we downgrade to scan all partitions.
if (expressionRewriter.isUnsupportedPartFnFound()) {
return partInfo.getDefs();
}
RangeSet<TypedKey> filterRange = rangeBuilder.buildRange(cnfExpr);
List<TiPartitionDef> pDefs = new ArrayList<>();
for (int i = 0; i < partExprs.size(); i++) {
Expression partExpr = partExprs.get(i);
// when we build range, we still need rewrite partition expression.
// If we have a year(purchased) < 1995 which cannot be normalized, we need
// to rewrite it into purchased < 1995 to let RangeSetBuilder be happy.
RangeSet<TypedKey> partRange = rangeBuilder.buildRange(expressionRewriter.rewrite(partExpr));
partRange.removeAll(filterRange.complement());
if (!partRange.isEmpty()) {
// part range is empty indicates this partition can be pruned.
pDefs.add(partInfo.getDefs().get(i));
}
}
return pDefs;
}
use of com.pingcap.tikv.key.TypedKey in project tispark by pingcap.
the class PredicateUtils method expressionToIndexRanges.
/**
* Build index ranges from access points and access conditions
*
* @param pointPredicates conditions converting to a single point access
* @param rangePredicate conditions converting to a range
* @return Index Range for scan
*/
public static List<IndexRange> expressionToIndexRanges(List<Expression> pointPredicates, Optional<Expression> rangePredicate, TiTableInfo table, TiIndexInfo index) {
requireNonNull(pointPredicates, "pointPredicates is null");
requireNonNull(rangePredicate, "rangePredicate is null");
ImmutableList.Builder<IndexRange> builder = ImmutableList.builder();
IndexRangeSetBuilder indexRangeBuilder = new IndexRangeSetBuilder(table, index);
if (pointPredicates.size() != 0) {
List<Key> pointKeys = expressionToPoints(pointPredicates, table, index);
for (Key key : pointKeys) {
if (rangePredicate.isPresent()) {
Set<Range<TypedKey>> ranges = indexRangeBuilder.buildRange(rangePredicate.get()).asRanges();
for (Range<TypedKey> range : ranges) {
builder.add(new IndexRange(key, range));
}
} else {
// no predicates with point keys leads to empty range encoding
builder.add(new IndexRange(key, null));
}
}
} else {
if (rangePredicate.isPresent()) {
Set<Range<TypedKey>> ranges = indexRangeBuilder.buildRange(rangePredicate.get()).asRanges();
for (Range<TypedKey> range : ranges) {
builder.add(new IndexRange(null, range));
}
} else {
// no filter at all means full range
builder.add(new IndexRange(null, Range.all()));
}
}
return builder.build();
}
use of com.pingcap.tikv.key.TypedKey in project tispark by pingcap.
the class PredicateUtilsTest method logicalBinaryExpressionToIndexRangesTest.
@Test
public void logicalBinaryExpressionToIndexRangesTest() {
TiTableInfo table = createTable();
TiIndexInfo index = table.getIndices().get(0);
TypedKey zero = TypedKey.toTypedKey(0, IntegerType.INT);
TypedKey one = TypedKey.toTypedKey(1, IntegerType.INT);
TypedKey two = TypedKey.toTypedKey(2, IntegerType.INT);
ColumnRef col1 = ColumnRef.create("c1", table);
Expression eq1 = greaterThan(col1, Constant.create(0));
Expression eq2 = lessThan(col1, Constant.create(2));
Expression eq3 = lessEqual(col1, Constant.create(1));
Expression eq4 = greaterThan(col1, Constant.create(2));
Expression and1 = and(eq1, eq2);
Expression and2 = and(eq1, eq3);
Expression and3 = and(eq2, eq3);
Expression or1 = or(eq1, eq2);
Expression or2 = or(eq1, eq4);
Expression or3 = or(eq3, eq4);
Expression xor1 = xor(eq1, eq2);
Expression xor2 = xor(eq1, eq3);
Expression xor3 = xor(eq2, eq3);
List<Range> ans1 = ImmutableList.of(Range.open(zero, two));
List<Range> ans2 = ImmutableList.of(Range.openClosed(zero, one));
List<Range> ans3 = ImmutableList.of(Range.atMost(one));
List<Range> ans4 = ImmutableList.of(Range.all());
List<Range> ans5 = ImmutableList.of(Range.greaterThan(zero));
List<Range> ans6 = ImmutableList.of(Range.atMost(one), Range.greaterThan(two));
List<Range> ans7 = ImmutableList.of(Range.atMost(zero), Range.atLeast(two));
List<Range> ans8 = ImmutableList.of(Range.atMost(zero), Range.greaterThan(one));
List<Range> ans9 = ImmutableList.of(Range.open(one, two));
Tests<Expression, List<Range>> logicalTests = new Tests<>();
logicalTests.addTestCase(and1, ans1);
logicalTests.addTestCase(and2, ans2);
logicalTests.addTestCase(and3, ans3);
logicalTests.addTestCase(or1, ans4);
logicalTests.addTestCase(or2, ans5);
logicalTests.addTestCase(or3, ans6);
logicalTests.addTestCase(xor1, ans7);
logicalTests.addTestCase(xor2, ans8);
logicalTests.addTestCase(xor3, ans9);
logicalTests.test((k, v) -> {
List<Expression> exprs = ImmutableList.of(k);
ScanSpec result = extractConditions(exprs, table, index);
List<IndexRange> irs = PredicateUtils.expressionToIndexRanges(result.getPointPredicates(), result.getRangePredicate(), table, index);
assertEquals(irs.size(), v.size());
for (int i = 0; i < irs.size(); i++) {
assertEquals(irs.get(i).getRange(), v.get(i));
}
});
}
Aggregations