Search in sources :

Example 1 with DataExceedsCapacityException

use of org.apache.phoenix.exception.DataExceedsCapacityException in project phoenix by apache.

the class PhoenixIndexBuilder method executeAtomicOp.

@Override
public List<Mutation> executeAtomicOp(Increment inc) throws IOException {
    byte[] opBytes = inc.getAttribute(ATOMIC_OP_ATTRIB);
    if (opBytes == null) {
        // Unexpected
        return null;
    }
    inc.setAttribute(ATOMIC_OP_ATTRIB, null);
    Put put = null;
    Delete delete = null;
    // We cannot neither use the time stamp in the Increment to set the Get time range
    // nor set the Put/Delete time stamp and have this be atomic as HBase does not
    // handle that. Though we disallow using ON DUPLICATE KEY clause when the
    // CURRENT_SCN is set, we still may have a time stamp set as of when the table
    // was resolved on the client side. We need to ignore this as well due to limitations
    // in HBase, but this isn't too bad as the time will be very close the the current
    // time anyway.
    long ts = HConstants.LATEST_TIMESTAMP;
    byte[] rowKey = inc.getRow();
    final Get get = new Get(rowKey);
    if (isDupKeyIgnore(opBytes)) {
        get.setFilter(new FirstKeyOnlyFilter());
        Result result = this.env.getRegion().get(get);
        return result.isEmpty() ? convertIncrementToPutInSingletonList(inc) : Collections.<Mutation>emptyList();
    }
    ByteArrayInputStream stream = new ByteArrayInputStream(opBytes);
    DataInputStream input = new DataInputStream(stream);
    boolean skipFirstOp = input.readBoolean();
    short repeat = input.readShort();
    final int[] estimatedSizeHolder = { 0 };
    List<Pair<PTable, List<Expression>>> operations = Lists.newArrayListWithExpectedSize(3);
    while (true) {
        ExpressionVisitor<Void> visitor = new StatelessTraverseAllExpressionVisitor<Void>() {

            @Override
            public Void visit(KeyValueColumnExpression expression) {
                get.addColumn(expression.getColumnFamily(), expression.getColumnQualifier());
                estimatedSizeHolder[0]++;
                return null;
            }
        };
        try {
            int nExpressions = WritableUtils.readVInt(input);
            List<Expression> expressions = Lists.newArrayListWithExpectedSize(nExpressions);
            for (int i = 0; i < nExpressions; i++) {
                Expression expression = ExpressionType.values()[WritableUtils.readVInt(input)].newInstance();
                expression.readFields(input);
                expressions.add(expression);
                expression.accept(visitor);
            }
            PTableProtos.PTable tableProto = PTableProtos.PTable.parseDelimitedFrom(input);
            PTable table = PTableImpl.createFromProto(tableProto);
            operations.add(new Pair<>(table, expressions));
        } catch (EOFException e) {
            break;
        }
    }
    int estimatedSize = estimatedSizeHolder[0];
    if (get.getFamilyMap().isEmpty()) {
        get.setFilter(new FirstKeyOnlyFilter());
    }
    MultiKeyValueTuple tuple;
    List<Cell> flattenedCells = null;
    List<Cell> cells = ((HRegion) this.env.getRegion()).get(get, false);
    if (cells.isEmpty()) {
        if (skipFirstOp) {
            if (operations.size() <= 1 && repeat <= 1) {
                return convertIncrementToPutInSingletonList(inc);
            }
            // Skip first operation (if first wasn't ON DUPLICATE KEY IGNORE)
            repeat--;
        }
        // Base current state off of new row
        flattenedCells = flattenCells(inc, estimatedSize);
        tuple = new MultiKeyValueTuple(flattenedCells);
    } else {
        // Base current state off of existing row
        tuple = new MultiKeyValueTuple(cells);
    }
    ImmutableBytesWritable ptr = new ImmutableBytesWritable();
    for (int opIndex = 0; opIndex < operations.size(); opIndex++) {
        Pair<PTable, List<Expression>> operation = operations.get(opIndex);
        PTable table = operation.getFirst();
        List<Expression> expressions = operation.getSecond();
        for (int j = 0; j < repeat; j++) {
            // repeater loop
            ptr.set(rowKey);
            // executed, not when the outer loop is exited. Hence we do it here, at the top of the loop.
            if (flattenedCells != null) {
                Collections.sort(flattenedCells, KeyValue.COMPARATOR);
            }
            PRow row = table.newRow(GenericKeyValueBuilder.INSTANCE, ts, ptr, false);
            for (int i = 0; i < expressions.size(); i++) {
                Expression expression = expressions.get(i);
                ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
                expression.evaluate(tuple, ptr);
                PColumn column = table.getColumns().get(i + 1);
                Object value = expression.getDataType().toObject(ptr, column.getSortOrder());
                // same type.
                if (!column.getDataType().isSizeCompatible(ptr, value, column.getDataType(), expression.getSortOrder(), expression.getMaxLength(), expression.getScale(), column.getMaxLength(), column.getScale())) {
                    throw new DataExceedsCapacityException(column.getDataType(), column.getMaxLength(), column.getScale());
                }
                column.getDataType().coerceBytes(ptr, value, expression.getDataType(), expression.getMaxLength(), expression.getScale(), expression.getSortOrder(), column.getMaxLength(), column.getScale(), column.getSortOrder(), table.rowKeyOrderOptimizable());
                byte[] bytes = ByteUtil.copyKeyBytesIfNecessary(ptr);
                row.setValue(column, bytes);
            }
            flattenedCells = Lists.newArrayListWithExpectedSize(estimatedSize);
            List<Mutation> mutations = row.toRowMutations();
            for (Mutation source : mutations) {
                flattenCells(source, flattenedCells);
            }
            tuple.setKeyValues(flattenedCells);
        }
        // Repeat only applies to first statement
        repeat = 1;
    }
    List<Mutation> mutations = Lists.newArrayListWithExpectedSize(2);
    for (int i = 0; i < tuple.size(); i++) {
        Cell cell = tuple.getValue(i);
        if (Type.codeToType(cell.getTypeByte()) == Type.Put) {
            if (put == null) {
                put = new Put(rowKey);
                transferAttributes(inc, put);
                mutations.add(put);
            }
            put.add(cell);
        } else {
            if (delete == null) {
                delete = new Delete(rowKey);
                transferAttributes(inc, delete);
                mutations.add(delete);
            }
            delete.addDeleteMarker(cell);
        }
    }
    return mutations;
}
Also used : Delete(org.apache.hadoop.hbase.client.Delete) PTable(org.apache.phoenix.schema.PTable) Result(org.apache.hadoop.hbase.client.Result) PRow(org.apache.phoenix.schema.PRow) PColumn(org.apache.phoenix.schema.PColumn) StatelessTraverseAllExpressionVisitor(org.apache.phoenix.expression.visitor.StatelessTraverseAllExpressionVisitor) EOFException(java.io.EOFException) List(java.util.List) KeyValueColumnExpression(org.apache.phoenix.expression.KeyValueColumnExpression) Cell(org.apache.hadoop.hbase.Cell) Pair(org.apache.hadoop.hbase.util.Pair) ImmutableBytesWritable(org.apache.hadoop.hbase.io.ImmutableBytesWritable) FirstKeyOnlyFilter(org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter) DataInputStream(java.io.DataInputStream) Put(org.apache.hadoop.hbase.client.Put) PTableProtos(org.apache.phoenix.coprocessor.generated.PTableProtos) HRegion(org.apache.hadoop.hbase.regionserver.HRegion) DataExceedsCapacityException(org.apache.phoenix.exception.DataExceedsCapacityException) ByteArrayInputStream(java.io.ByteArrayInputStream) KeyValueColumnExpression(org.apache.phoenix.expression.KeyValueColumnExpression) Expression(org.apache.phoenix.expression.Expression) Get(org.apache.hadoop.hbase.client.Get) MultiKeyValueTuple(org.apache.phoenix.schema.tuple.MultiKeyValueTuple) Mutation(org.apache.hadoop.hbase.client.Mutation)

Example 2 with DataExceedsCapacityException

use of org.apache.phoenix.exception.DataExceedsCapacityException in project phoenix by apache.

the class DecimalAddExpression method evaluate.

@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
        Expression childExpr = children.get(i);
        if (!childExpr.evaluate(tuple, ptr)) {
            return false;
        }
        if (ptr.getLength() == 0) {
            return true;
        }
        PDataType childType = childExpr.getDataType();
        SortOrder childSortOrder = childExpr.getSortOrder();
        BigDecimal bd = (BigDecimal) PDecimal.INSTANCE.toObject(ptr, childType, childSortOrder);
        if (result == null) {
            result = bd;
        } else {
            result = result.add(bd);
        }
    }
    if (maxLength != null || scale != null) {
        result = NumberUtil.setDecimalWidthAndScale(result, maxLength, scale);
    }
    if (result == null) {
        throw new DataExceedsCapacityException(PDecimal.INSTANCE, maxLength, scale);
    }
    ptr.set(PDecimal.INSTANCE.toBytes(result));
    return true;
}
Also used : DataExceedsCapacityException(org.apache.phoenix.exception.DataExceedsCapacityException) PDataType(org.apache.phoenix.schema.types.PDataType) SortOrder(org.apache.phoenix.schema.SortOrder) BigDecimal(java.math.BigDecimal)

Example 3 with DataExceedsCapacityException

use of org.apache.phoenix.exception.DataExceedsCapacityException in project phoenix by apache.

the class DecimalMultiplyExpression method evaluate.

@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
        Expression childExpr = children.get(i);
        if (!childExpr.evaluate(tuple, ptr)) {
            return false;
        }
        if (ptr.getLength() == 0) {
            return true;
        }
        PDataType childType = children.get(i).getDataType();
        SortOrder childSortOrder = children.get(i).getSortOrder();
        BigDecimal bd = (BigDecimal) PDecimal.INSTANCE.toObject(ptr, childType, childSortOrder);
        if (result == null) {
            result = bd;
        } else {
            result = result.multiply(bd);
        }
    }
    if (getMaxLength() != null || getScale() != null) {
        result = NumberUtil.setDecimalWidthAndScale(result, getMaxLength(), getScale());
    }
    if (result == null) {
        throw new DataExceedsCapacityException(PDecimal.INSTANCE, getMaxLength(), getScale());
    }
    ptr.set(PDecimal.INSTANCE.toBytes(result));
    return true;
}
Also used : DataExceedsCapacityException(org.apache.phoenix.exception.DataExceedsCapacityException) PDataType(org.apache.phoenix.schema.types.PDataType) SortOrder(org.apache.phoenix.schema.SortOrder) BigDecimal(java.math.BigDecimal)

Example 4 with DataExceedsCapacityException

use of org.apache.phoenix.exception.DataExceedsCapacityException in project phoenix by apache.

the class DecimalSubtractExpression method evaluate.

@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
        Expression childExpr = children.get(i);
        if (!childExpr.evaluate(tuple, ptr)) {
            return false;
        }
        if (ptr.getLength() == 0) {
            return true;
        }
        PDataType childType = childExpr.getDataType();
        boolean isDate = childType.isCoercibleTo(PDate.INSTANCE);
        SortOrder childSortOrder = childExpr.getSortOrder();
        BigDecimal bd = isDate ? BigDecimal.valueOf(childType.getCodec().decodeLong(ptr, childSortOrder)) : (BigDecimal) PDecimal.INSTANCE.toObject(ptr, childType, childSortOrder);
        if (result == null) {
            result = bd;
        } else {
            result = result.subtract(bd);
            /*
                 * Special case for date subtraction - note that only first two expression may be dates.
                 * We need to convert the date to a unit of "days" because that's what sql expects.
                 */
            if (isDate) {
                result = result.divide(BD_MILLIS_IN_DAY, PDataType.DEFAULT_MATH_CONTEXT);
            }
        }
    }
    if (maxLength != null || scale != null) {
        result = NumberUtil.setDecimalWidthAndScale(result, maxLength, scale);
    }
    if (result == null) {
        throw new DataExceedsCapacityException(PDecimal.INSTANCE, maxLength, scale);
    }
    ptr.set(PDecimal.INSTANCE.toBytes(result));
    return true;
}
Also used : DataExceedsCapacityException(org.apache.phoenix.exception.DataExceedsCapacityException) PDataType(org.apache.phoenix.schema.types.PDataType) SortOrder(org.apache.phoenix.schema.SortOrder) BigDecimal(java.math.BigDecimal)

Example 5 with DataExceedsCapacityException

use of org.apache.phoenix.exception.DataExceedsCapacityException in project phoenix by apache.

the class ArithmeticOperationTest method testDecimalAddition.

// Addition
// result scale should be: max(ls, rs)
// result precision should be: max(lp - ls, rp - rs) + 1 + max(ls, rs)
@Test
public void testDecimalAddition() throws Exception {
    LiteralExpression op1, op2, op3;
    List<Expression> children;
    DecimalAddExpression e;
    op1 = LiteralExpression.newConstant(new BigDecimal("1234567890123456789012345678901"), PDecimal.INSTANCE, 31, 0);
    op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0);
    children = Arrays.<Expression>asList(op1, op2);
    e = new DecimalAddExpression(children);
    assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1234567890123456789012345691246"));
    op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0);
    op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2);
    children = Arrays.<Expression>asList(op1, op2);
    e = new DecimalAddExpression(children);
    assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("12468.45"));
    // Exceeds precision.
    op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0);
    op2 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0);
    children = Arrays.<Expression>asList(op1, op2);
    e = new DecimalAddExpression(children);
    try {
        e.evaluate(null, new ImmutableBytesWritable());
        fail("Evaluation should have failed");
    } catch (DataExceedsCapacityException ex) {
    }
    // Pass since we roll out imposing precisioin and scale.
    op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0);
    op2 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0);
    op3 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0);
    children = Arrays.<Expression>asList(op1, op2, op3);
    e = new DecimalAddExpression(children);
    assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("99999999999999999999999999999999999999"));
    // Exceeds scale.
    op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0);
    op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2);
    children = Arrays.<Expression>asList(op1, op2);
    e = new DecimalAddExpression(children);
    try {
        e.evaluate(null, new ImmutableBytesWritable());
        fail("Evaluation should have failed");
    } catch (DataExceedsCapacityException ex) {
    }
    // Decimal with no precision and scale.
    op1 = LiteralExpression.newConstant(new BigDecimal("9999.1"), PDecimal.INSTANCE);
    op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4);
    children = Arrays.<Expression>asList(op1, op2);
    e = new DecimalAddExpression(children);
    assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("10000.2111"));
}
Also used : ImmutableBytesWritable(org.apache.hadoop.hbase.io.ImmutableBytesWritable) DataExceedsCapacityException(org.apache.phoenix.exception.DataExceedsCapacityException) BigDecimal(java.math.BigDecimal) Test(org.junit.Test)

Aggregations

DataExceedsCapacityException (org.apache.phoenix.exception.DataExceedsCapacityException)12 BigDecimal (java.math.BigDecimal)8 ImmutableBytesWritable (org.apache.hadoop.hbase.io.ImmutableBytesWritable)6 PDataType (org.apache.phoenix.schema.types.PDataType)6 Test (org.junit.Test)4 Expression (org.apache.phoenix.expression.Expression)3 SortOrder (org.apache.phoenix.schema.SortOrder)3 SQLException (java.sql.SQLException)2 List (java.util.List)2 Cell (org.apache.hadoop.hbase.Cell)2 Delete (org.apache.hadoop.hbase.client.Delete)2 Mutation (org.apache.hadoop.hbase.client.Mutation)2 Put (org.apache.hadoop.hbase.client.Put)2 PColumn (org.apache.phoenix.schema.PColumn)2 PRow (org.apache.phoenix.schema.PRow)2 PTable (org.apache.phoenix.schema.PTable)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 DataInputStream (java.io.DataInputStream)1 EOFException (java.io.EOFException)1 IOException (java.io.IOException)1