use of org.apache.phoenix.expression.Expression in project phoenix by apache.
the class ArrayModifierFunction method evaluate.
@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
Expression arrayExpr = null;
PDataType baseDataType = null;
Expression otherExpr = null;
PDataType otherExpressionType = null;
if (getLHSExpr().getDataType().isArrayType()) {
arrayExpr = getLHSExpr();
baseDataType = getLHSBaseType();
otherExpr = getRHSExpr();
otherExpressionType = getRHSBaseType();
} else {
arrayExpr = getRHSExpr();
baseDataType = getRHSBaseType();
otherExpr = getLHSExpr();
otherExpressionType = getLHSBaseType();
}
if (!arrayExpr.evaluate(tuple, ptr)) {
return false;
} else if (ptr.getLength() == 0) {
return true;
}
int arrayLength = PArrayDataType.getArrayLength(ptr, baseDataType, arrayExpr.getMaxLength());
int length = ptr.getLength();
int offset = ptr.getOffset();
byte[] arrayBytes = ptr.get();
otherExpr.evaluate(tuple, ptr);
checkSizeCompatibility(ptr, otherExpr.getSortOrder(), arrayExpr, baseDataType, otherExpr, otherExpressionType);
coerceBytes(ptr, arrayExpr, baseDataType, otherExpr, otherExpressionType);
return modifierFunction(ptr, length, offset, arrayBytes, baseDataType, arrayLength, getMaxLength(), arrayExpr);
}
use of org.apache.phoenix.expression.Expression in project phoenix by apache.
the class CeilDecimalExpression method create.
public static Expression create(List<Expression> exprs) throws SQLException {
Expression expr = exprs.get(0);
if (expr.getDataType().isCoercibleTo(PLong.INSTANCE)) {
return expr;
}
if (exprs.size() == 1) {
Expression scaleExpr = LiteralExpression.newConstant(0, PInteger.INSTANCE, Determinism.ALWAYS);
exprs = Lists.newArrayList(expr, scaleExpr);
}
return new CeilDecimalExpression(exprs);
}
use of org.apache.phoenix.expression.Expression in project phoenix by apache.
the class CeilTimestampExpression method create.
public static Expression create(List<Expression> children) throws SQLException {
Expression firstChild = children.get(0);
PDataType firstChildDataType = firstChild.getDataType();
String timeUnit = (String) ((LiteralExpression) children.get(1)).getValue();
if (TimeUnit.MILLISECOND.toString().equalsIgnoreCase(timeUnit)) {
return new CeilTimestampExpression(children);
}
// Coerce TIMESTAMP to DATE, as the nanos has no affect
List<Expression> newChildren = Lists.newArrayListWithExpectedSize(children.size());
newChildren.add(CoerceExpression.create(firstChild, firstChildDataType == PTimestamp.INSTANCE ? PDate.INSTANCE : PUnsignedDate.INSTANCE));
newChildren.addAll(children.subList(1, children.size()));
return CeilDateExpression.create(newChildren);
}
use of org.apache.phoenix.expression.Expression in project phoenix by apache.
the class RoundDecimalExpression method newKeyPart.
@Override
public KeyPart newKeyPart(final KeyPart childPart) {
return new KeyPart() {
private final List<Expression> extractNodes = Collections.<Expression>singletonList(RoundDecimalExpression.this);
@Override
public PColumn getColumn() {
return childPart.getColumn();
}
@Override
public List<Expression> getExtractNodes() {
return extractNodes;
}
@Override
public KeyRange getKeyRange(CompareFilter.CompareOp op, Expression rhs) {
final BigDecimal rhsDecimal = (BigDecimal) PDecimal.INSTANCE.toObject(evaluateExpression(rhs));
// than needed for a match, it's impossible for there to be any matches
if (op == CompareFilter.CompareOp.EQUAL && !hasEnoughPrecisionToProduce(rhsDecimal)) {
return KeyRange.EMPTY_RANGE;
}
// if the decimal needs to be rounded, round it such that the given
// operator will still be valid
BigDecimal roundedDecimal = roundAndPreserveOperator(rhsDecimal, op);
// the range of big decimals that could be rounded to produce the rounded result
// alternatively, the "rounding bucket" that this decimal falls into
final KeyRange equalityRange = getInputRangeProducing(roundedDecimal);
boolean lowerInclusive = equalityRange.isLowerInclusive();
boolean upperInclusive = equalityRange.isUpperInclusive();
byte[] lowerRange = KeyRange.UNBOUND;
byte[] upperRange = KeyRange.UNBOUND;
switch(op) {
case EQUAL:
return equalityRange;
case GREATER:
// from the equality range and up, NOT including the equality range
lowerRange = equalityRange.getUpperRange();
lowerInclusive = !equalityRange.isUpperInclusive();
break;
case GREATER_OR_EQUAL:
// from the equality range and up, including the equality range
lowerRange = equalityRange.getLowerRange();
break;
case LESS:
// from the equality range and down, NOT including the equality range
upperRange = equalityRange.getLowerRange();
upperInclusive = !equalityRange.isLowerInclusive();
break;
case LESS_OR_EQUAL:
// from the equality range and down, including the equality range
upperRange = equalityRange.getUpperRange();
break;
default:
throw new AssertionError("Invalid CompareOp: " + op);
}
return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, upperInclusive);
}
/**
* Produces a the given decimal rounded to this rounding expression's scale. If the
* decimal requires more scale precision to produce than this expression has, as in
* ROUND(?, 2) > 2.0098974, it ensures that the decimal is rounded such that the
* given operator will still produce correct results.
* @param decimal the decimal to round with this expression's scale
* @param op the operator to preserve comparison with in the event of lost precision
* @return the rounded decimal
*/
private BigDecimal roundAndPreserveOperator(BigDecimal decimal, CompareFilter.CompareOp op) {
final BigDecimal rounded = roundToScale(decimal);
// if we lost information, make sure that the rounding didn't break the operator
if (!hasEnoughPrecisionToProduce(decimal)) {
switch(op) {
case GREATER_OR_EQUAL:
// 'ROUND(dec, 2) >= 2.01' but should be 'ROUND(dec, 2) >= 2.02'
if (decimal.compareTo(rounded) > 0) {
return stepNextInScale(rounded);
}
break;
case GREATER:
// 'ROUND(dec, 2) > 2.02' but should be 'ROUND(dec, 2) > 2.01'
if (decimal.compareTo(rounded) < 0) {
return stepPrevInScale(rounded);
}
break;
case LESS_OR_EQUAL:
// 'ROUND(dec, 2) < 2.02' but should be 'ROUND(dec, 2) < 2.01'
if (decimal.compareTo(rounded) < 0) {
return stepPrevInScale(rounded);
}
break;
case LESS:
// 'ROUND(dec, 2) <= 2.01' but should be 'ROUND(dec, 2) <= 2.02'
if (decimal.compareTo(rounded) > 0) {
return stepNextInScale(rounded);
}
break;
}
}
// otherwise, rounding has not affected the operator, so return normally
return rounded;
}
@Override
public PTable getTable() {
return childPart.getTable();
}
};
}
use of org.apache.phoenix.expression.Expression in project phoenix by apache.
the class RoundTimestampExpression method create.
public static Expression create(List<Expression> children) throws SQLException {
Expression firstChild = children.get(0);
PDataType firstChildDataType = firstChild.getDataType();
String timeUnit = (String) ((LiteralExpression) children.get(1)).getValue();
LiteralExpression multiplierExpr = (LiteralExpression) children.get(2);
/*
* When rounding off timestamp to milliseconds, nanos play a part only when the multiplier value
* is equal to 1. This is because for cases when multiplier value is greater than 1, number of nanos/multiplier
* will always be less than half the nanos in a millisecond.
*/
if ((timeUnit == null || TimeUnit.MILLISECOND.toString().equalsIgnoreCase(timeUnit)) && ((Number) multiplierExpr.getValue()).intValue() == 1) {
return new RoundTimestampExpression(children);
}
// Coerce TIMESTAMP to DATE, as the nanos has no affect
List<Expression> newChildren = Lists.newArrayListWithExpectedSize(children.size());
newChildren.add(CoerceExpression.create(firstChild, firstChildDataType == PTimestamp.INSTANCE ? PDate.INSTANCE : PUnsignedDate.INSTANCE));
newChildren.addAll(children.subList(1, children.size()));
return RoundDateExpression.create(newChildren);
}
Aggregations