use of org.apache.phoenix.expression.function.ArrayElemRefExpression in project phoenix by apache.
the class ComparisonExpression method create.
public static Expression create(CompareOp op, List<Expression> children, ImmutableBytesWritable ptr, boolean rowKeyOrderOptimizable) throws SQLException {
Expression lhsExpr = children.get(0);
Expression rhsExpr = children.get(1);
PDataType lhsExprDataType = lhsExpr.getDataType();
PDataType rhsExprDataType = rhsExpr.getDataType();
if ((lhsExpr instanceof RowValueConstructorExpression || rhsExpr instanceof RowValueConstructorExpression) && !(lhsExpr instanceof ArrayElemRefExpression) && !(rhsExpr instanceof ArrayElemRefExpression)) {
if (op == CompareOp.EQUAL || op == CompareOp.NOT_EQUAL) {
List<Expression> andNodes = Lists.<Expression>newArrayListWithExpectedSize(Math.max(lhsExpr.getChildren().size(), rhsExpr.getChildren().size()));
rewriteRVCAsEqualityExpression(lhsExpr, rhsExpr, andNodes, ptr, rowKeyOrderOptimizable);
Expression expr = AndExpression.create(andNodes);
if (op == CompareOp.NOT_EQUAL) {
expr = NotExpression.create(expr, ptr);
}
return expr;
}
rhsExpr = RowValueConstructorExpression.coerce(lhsExpr, rhsExpr, op, rowKeyOrderOptimizable);
// a non rvc with a rvc.
if (!(lhsExpr instanceof RowValueConstructorExpression)) {
lhsExpr = new RowValueConstructorExpression(Collections.singletonList(lhsExpr), lhsExpr.isStateless());
}
children = Arrays.asList(lhsExpr, rhsExpr);
} else if (lhsExprDataType != null && rhsExprDataType != null && !lhsExprDataType.isComparableTo(rhsExprDataType)) {
throw TypeMismatchException.newException(lhsExprDataType, rhsExprDataType, toString(op, children));
}
Determinism determinism = lhsExpr.getDeterminism().combine(rhsExpr.getDeterminism());
Object lhsValue = null;
// TODO: use lhsExpr.isStateless instead
if (lhsExpr instanceof LiteralExpression) {
lhsValue = ((LiteralExpression) lhsExpr).getValue();
if (lhsValue == null) {
return LiteralExpression.newConstant(null, PBoolean.INSTANCE, lhsExpr.getDeterminism());
}
}
Object rhsValue = null;
// TODO: use lhsExpr.isStateless instead
if (rhsExpr instanceof LiteralExpression) {
rhsValue = ((LiteralExpression) rhsExpr).getValue();
if (rhsValue == null) {
return LiteralExpression.newConstant(null, PBoolean.INSTANCE, rhsExpr.getDeterminism());
}
}
if (lhsValue != null && rhsValue != null) {
return LiteralExpression.newConstant(ByteUtil.compare(op, lhsExprDataType.compareTo(lhsValue, rhsValue, rhsExprDataType)), determinism);
}
// to put constants on the LHS, we don't need to check the RHS.
if (rhsValue != null) {
// into account the comparison operator.
if (rhsExprDataType != lhsExprDataType || rhsExpr.getSortOrder() != lhsExpr.getSortOrder() || (rhsExprDataType.isFixedWidth() && rhsExpr.getMaxLength() != null && lhsExprDataType.isFixedWidth() && lhsExpr.getMaxLength() != null && rhsExpr.getMaxLength() < lhsExpr.getMaxLength())) {
// TODO: if lengths are unequal and fixed width?
if (rhsExprDataType.isCoercibleTo(lhsExprDataType, rhsValue)) {
// will convert 2.0 -> 2
children = Arrays.asList(children.get(0), LiteralExpression.newConstant(rhsValue, lhsExprDataType, lhsExpr.getMaxLength(), null, lhsExpr.getSortOrder(), determinism, rowKeyOrderOptimizable));
} else if (op == CompareOp.EQUAL) {
return LiteralExpression.newConstant(false, PBoolean.INSTANCE, Determinism.ALWAYS);
} else if (op == CompareOp.NOT_EQUAL) {
return LiteralExpression.newConstant(true, PBoolean.INSTANCE, Determinism.ALWAYS);
} else {
// TODO: generalize this with PDataType.getMinValue(), PDataTypeType.getMaxValue() methods
if (rhsExprDataType == PDecimal.INSTANCE) {
/*
* We're comparing an int/long to a constant decimal with a fraction part.
* We need the types to match in case this is used to form a key. To form the start/stop key,
* we need to adjust the decimal by truncating it or taking its ceiling, depending on the comparison
* operator, to get a whole number.
*/
int increment = 0;
switch(op) {
case GREATER_OR_EQUAL:
case // get next whole number
LESS:
increment = 1;
default:
// Else, we truncate the value
BigDecimal bd = (BigDecimal) rhsValue;
rhsValue = bd.longValue() + increment;
children = Arrays.asList(lhsExpr, LiteralExpression.newConstant(rhsValue, lhsExprDataType, lhsExpr.getSortOrder(), rhsExpr.getDeterminism()));
break;
}
} else if (rhsExprDataType == PLong.INSTANCE) {
/*
* We are comparing an int, unsigned_int to a long, or an unsigned_long to a negative long.
* int has range of -2147483648 to 2147483647, and unsigned_int has a value range of 0 to 4294967295.
*
* If lhs is int or unsigned_int, since we already determined that we cannot coerce the rhs
* to become the lhs, we know the value on the rhs is greater than lhs if it's positive, or smaller than
* lhs if it's negative.
*
* If lhs is an unsigned_long, then we know the rhs is definitely a negative long. rhs in this case
* will always be bigger than rhs.
*/
if (lhsExprDataType == PInteger.INSTANCE || lhsExprDataType == PUnsignedInt.INSTANCE) {
switch(op) {
case LESS:
case LESS_OR_EQUAL:
if ((Long) rhsValue > 0) {
return LiteralExpression.newConstant(true, PBoolean.INSTANCE, determinism);
} else {
return LiteralExpression.newConstant(false, PBoolean.INSTANCE, determinism);
}
case GREATER:
case GREATER_OR_EQUAL:
if ((Long) rhsValue > 0) {
return LiteralExpression.newConstant(false, PBoolean.INSTANCE, determinism);
} else {
return LiteralExpression.newConstant(true, PBoolean.INSTANCE, determinism);
}
default:
break;
}
} else if (lhsExprDataType == PUnsignedLong.INSTANCE) {
switch(op) {
case LESS:
case LESS_OR_EQUAL:
return LiteralExpression.newConstant(false, PBoolean.INSTANCE, determinism);
case GREATER:
case GREATER_OR_EQUAL:
return LiteralExpression.newConstant(true, PBoolean.INSTANCE, determinism);
default:
break;
}
}
children = Arrays.asList(lhsExpr, LiteralExpression.newConstant(rhsValue, rhsExprDataType, lhsExpr.getSortOrder(), determinism));
}
}
}
// a fixed length expression.
if (children.get(1).getMaxLength() != null && lhsExpr.getMaxLength() != null && lhsExpr.getMaxLength() < children.get(1).getMaxLength()) {
switch(op) {
case EQUAL:
return LiteralExpression.newConstant(false, PBoolean.INSTANCE, determinism);
case NOT_EQUAL:
return LiteralExpression.newConstant(true, PBoolean.INSTANCE, determinism);
default:
break;
}
}
}
return new ComparisonExpression(children, op);
}
use of org.apache.phoenix.expression.function.ArrayElemRefExpression in project phoenix by apache.
the class ArrayConstructorExpressionTest method testLeadingNulls.
@Test
public void testLeadingNulls() throws Exception {
List<Expression> children = Lists.newArrayListWithExpectedSize(4);
LiteralExpression nullExpression = LiteralExpression.newConstant(null);
children.add(nullExpression);
children.add(nullExpression);
children.add(LiteralExpression.newConstant(BYTE_ARRAY1, PVarbinary.INSTANCE));
children.add(LiteralExpression.newConstant(BYTE_ARRAY2, PVarbinary.INSTANCE));
ArrayConstructorExpression arrayConstructorExpression = new ArrayConstructorExpression(children, PVarbinary.INSTANCE, false);
ImmutableBytesPtr ptr = new ImmutableBytesPtr();
ArrayElemRefExpression arrayElemRefExpression = new ArrayElemRefExpression(Lists.<Expression>newArrayList(arrayConstructorExpression));
arrayElemRefExpression.setIndex(1);
arrayElemRefExpression.evaluate(null, ptr);
assertArrayEquals(ByteUtil.EMPTY_BYTE_ARRAY, ptr.copyBytesIfNecessary());
arrayElemRefExpression.setIndex(2);
arrayElemRefExpression.evaluate(null, ptr);
assertArrayEquals(ByteUtil.EMPTY_BYTE_ARRAY, ptr.copyBytesIfNecessary());
arrayElemRefExpression.setIndex(3);
arrayElemRefExpression.evaluate(null, ptr);
assertArrayEquals(BYTE_ARRAY1, ptr.copyBytesIfNecessary());
arrayElemRefExpression.setIndex(4);
arrayElemRefExpression.evaluate(null, ptr);
assertArrayEquals(BYTE_ARRAY2, ptr.copyBytesIfNecessary());
}
Aggregations