Search in sources :

Example 1 with ArrayElemRefExpression

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);
}
Also used : ArrayElemRefExpression(org.apache.phoenix.expression.function.ArrayElemRefExpression) PDataType(org.apache.phoenix.schema.types.PDataType) ArrayElemRefExpression(org.apache.phoenix.expression.function.ArrayElemRefExpression) PLong(org.apache.phoenix.schema.types.PLong) PUnsignedLong(org.apache.phoenix.schema.types.PUnsignedLong) BigDecimal(java.math.BigDecimal)

Example 2 with ArrayElemRefExpression

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());
}
Also used : ArrayElemRefExpression(org.apache.phoenix.expression.function.ArrayElemRefExpression) ArrayElemRefExpression(org.apache.phoenix.expression.function.ArrayElemRefExpression) ImmutableBytesPtr(org.apache.phoenix.hbase.index.util.ImmutableBytesPtr) Test(org.junit.Test)

Aggregations

ArrayElemRefExpression (org.apache.phoenix.expression.function.ArrayElemRefExpression)2 BigDecimal (java.math.BigDecimal)1 ImmutableBytesPtr (org.apache.phoenix.hbase.index.util.ImmutableBytesPtr)1 PDataType (org.apache.phoenix.schema.types.PDataType)1 PLong (org.apache.phoenix.schema.types.PLong)1 PUnsignedLong (org.apache.phoenix.schema.types.PUnsignedLong)1 Test (org.junit.Test)1