Search in sources :

Example 1 with ValueGetterTuple

use of org.apache.phoenix.schema.tuple.ValueGetterTuple in project phoenix by apache.

the class IndexMaintainer method buildRowKey.

public byte[] buildRowKey(ValueGetter valueGetter, ImmutableBytesWritable rowKeyPtr, byte[] regionStartKey, byte[] regionEndKey) {
    ImmutableBytesWritable ptr = new ImmutableBytesWritable();
    boolean prependRegionStartKey = isLocalIndex && regionStartKey != null;
    boolean isIndexSalted = !isLocalIndex && nIndexSaltBuckets > 0;
    int prefixKeyLength = prependRegionStartKey ? (regionStartKey.length != 0 ? regionStartKey.length : regionEndKey.length) : 0;
    TrustedByteArrayOutputStream stream = new TrustedByteArrayOutputStream(estimatedIndexRowKeyBytes + (prependRegionStartKey ? prefixKeyLength : 0));
    DataOutput output = new DataOutputStream(stream);
    try {
        // For local indexes, we must prepend the row key with the start region key
        if (prependRegionStartKey) {
            if (regionStartKey.length == 0) {
                output.write(new byte[prefixKeyLength]);
            } else {
                output.write(regionStartKey);
            }
        }
        if (isIndexSalted) {
            // will be set at end to index salt byte
            output.write(0);
        }
        // The dataRowKeySchema includes the salt byte field,
        // so we must adjust for that here.
        int dataPosOffset = isDataTableSalted ? 1 : 0;
        BitSet viewConstantColumnBitSet = this.rowKeyMetaData.getViewConstantColumnBitSet();
        int nIndexedColumns = getIndexPkColumnCount() - getNumViewConstants();
        int[][] dataRowKeyLocator = new int[2][nIndexedColumns];
        // Skip data table salt byte
        int maxRowKeyOffset = rowKeyPtr.getOffset() + rowKeyPtr.getLength();
        dataRowKeySchema.iterator(rowKeyPtr, ptr, dataPosOffset);
        if (viewIndexId != null) {
            output.write(viewIndexId);
        }
        if (isMultiTenant) {
            dataRowKeySchema.next(ptr, dataPosOffset, maxRowKeyOffset);
            output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
            if (!dataRowKeySchema.getField(dataPosOffset).getDataType().isFixedWidth()) {
                output.writeByte(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, ptr.getLength() == 0, dataRowKeySchema.getField(dataPosOffset)));
            }
            dataPosOffset++;
        }
        // Write index row key
        for (int i = dataPosOffset; i < dataRowKeySchema.getFieldCount(); i++) {
            Boolean hasValue = dataRowKeySchema.next(ptr, i, maxRowKeyOffset);
            // same for all rows in this index)
            if (!viewConstantColumnBitSet.get(i)) {
                int pos = rowKeyMetaData.getIndexPkPosition(i - dataPosOffset);
                if (Boolean.TRUE.equals(hasValue)) {
                    dataRowKeyLocator[0][pos] = ptr.getOffset();
                    dataRowKeyLocator[1][pos] = ptr.getLength();
                } else {
                    dataRowKeyLocator[0][pos] = 0;
                    dataRowKeyLocator[1][pos] = 0;
                }
            }
        }
        BitSet descIndexColumnBitSet = rowKeyMetaData.getDescIndexColumnBitSet();
        Iterator<Expression> expressionIterator = indexedExpressions.iterator();
        for (int i = 0; i < nIndexedColumns; i++) {
            PDataType dataColumnType;
            boolean isNullable;
            SortOrder dataSortOrder;
            if (dataPkPosition[i] == EXPRESSION_NOT_PRESENT) {
                Expression expression = expressionIterator.next();
                dataColumnType = expression.getDataType();
                dataSortOrder = expression.getSortOrder();
                isNullable = expression.isNullable();
                expression.evaluate(new ValueGetterTuple(valueGetter), ptr);
            } else {
                Field field = dataRowKeySchema.getField(dataPkPosition[i]);
                dataColumnType = field.getDataType();
                ptr.set(rowKeyPtr.get(), dataRowKeyLocator[0][i], dataRowKeyLocator[1][i]);
                dataSortOrder = field.getSortOrder();
                isNullable = field.isNullable();
            }
            boolean isDataColumnInverted = dataSortOrder != SortOrder.ASC;
            PDataType indexColumnType = IndexUtil.getIndexColumnDataType(isNullable, dataColumnType);
            boolean isBytesComparable = dataColumnType.isBytesComparableWith(indexColumnType);
            boolean isIndexColumnDesc = descIndexColumnBitSet.get(i);
            if (isBytesComparable && isDataColumnInverted == isIndexColumnDesc) {
                output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
            } else {
                if (!isBytesComparable) {
                    indexColumnType.coerceBytes(ptr, dataColumnType, dataSortOrder, SortOrder.getDefault());
                }
                if (isDataColumnInverted != isIndexColumnDesc) {
                    writeInverted(ptr.get(), ptr.getOffset(), ptr.getLength(), output);
                } else {
                    output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
                }
            }
            if (!indexColumnType.isFixedWidth()) {
                output.writeByte(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, ptr.getLength() == 0, isIndexColumnDesc ? SortOrder.DESC : SortOrder.ASC));
            }
        }
        int length = stream.size();
        int minLength = length - maxTrailingNulls;
        byte[] indexRowKey = stream.getBuffer();
        // Remove trailing nulls
        while (length > minLength && indexRowKey[length - 1] == QueryConstants.SEPARATOR_BYTE) {
            length--;
        }
        if (isIndexSalted) {
            // Set salt byte
            byte saltByte = SaltingUtil.getSaltingByte(indexRowKey, SaltingUtil.NUM_SALTING_BYTES, length - SaltingUtil.NUM_SALTING_BYTES, nIndexSaltBuckets);
            indexRowKey[0] = saltByte;
        }
        return indexRowKey.length == length ? indexRowKey : Arrays.copyOf(indexRowKey, length);
    } catch (IOException e) {
        // Impossible
        throw new RuntimeException(e);
    } finally {
        try {
            stream.close();
        } catch (IOException e) {
            // Impossible
            throw new RuntimeException(e);
        }
    }
}
Also used : DataOutput(java.io.DataOutput) ImmutableBytesWritable(org.apache.hadoop.hbase.io.ImmutableBytesWritable) DataOutputStream(java.io.DataOutputStream) BitSet(org.apache.phoenix.util.BitSet) SortOrder(org.apache.phoenix.schema.SortOrder) TrustedByteArrayOutputStream(org.apache.phoenix.util.TrustedByteArrayOutputStream) IOException(java.io.IOException) Field(org.apache.phoenix.schema.ValueSchema.Field) PDataType(org.apache.phoenix.schema.types.PDataType) KeyValueColumnExpression(org.apache.phoenix.expression.KeyValueColumnExpression) SingleCellConstructorExpression(org.apache.phoenix.expression.SingleCellConstructorExpression) Expression(org.apache.phoenix.expression.Expression) SingleCellColumnExpression(org.apache.phoenix.expression.SingleCellColumnExpression) CoerceExpression(org.apache.phoenix.expression.CoerceExpression) LiteralExpression(org.apache.phoenix.expression.LiteralExpression) ValueGetterTuple(org.apache.phoenix.schema.tuple.ValueGetterTuple)

Example 2 with ValueGetterTuple

use of org.apache.phoenix.schema.tuple.ValueGetterTuple in project phoenix by apache.

the class IndexMaintainer method buildUpdateMutation.

public Put buildUpdateMutation(KeyValueBuilder kvBuilder, ValueGetter valueGetter, ImmutableBytesWritable dataRowKeyPtr, long ts, byte[] regionStartKey, byte[] regionEndKey) throws IOException {
    byte[] indexRowKey = this.buildRowKey(valueGetter, dataRowKeyPtr, regionStartKey, regionEndKey);
    Put put = null;
    // New row being inserted: add the empty key value
    if (valueGetter == null || valueGetter.getLatestValue(dataEmptyKeyValueRef) == null) {
        put = new Put(indexRowKey);
        // add the keyvalue for the empty row
        put.add(kvBuilder.buildPut(new ImmutableBytesPtr(indexRowKey), this.getEmptyKeyValueFamily(), dataEmptyKeyValueRef.getQualifierWritable(), ts, // set the value to the empty column name
        dataEmptyKeyValueRef.getQualifierWritable()));
        put.setDurability(!indexWALDisabled ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
    }
    ImmutableBytesPtr rowKey = new ImmutableBytesPtr(indexRowKey);
    if (immutableStorageScheme != ImmutableStorageScheme.ONE_CELL_PER_COLUMN) {
        // map from index column family to list of pair of index column and data column (for covered columns)
        Map<ImmutableBytesPtr, List<Pair<ColumnReference, ColumnReference>>> familyToColListMap = Maps.newHashMap();
        for (ColumnReference ref : this.getCoveredColumns()) {
            ColumnReference indexColRef = this.coveredColumnsMap.get(ref);
            ImmutableBytesPtr cf = new ImmutableBytesPtr(indexColRef.getFamily());
            if (!familyToColListMap.containsKey(cf)) {
                familyToColListMap.put(cf, Lists.<Pair<ColumnReference, ColumnReference>>newArrayList());
            }
            familyToColListMap.get(cf).add(Pair.newPair(indexColRef, ref));
        }
        // iterate over each column family and create a byte[] containing all the columns 
        for (Entry<ImmutableBytesPtr, List<Pair<ColumnReference, ColumnReference>>> entry : familyToColListMap.entrySet()) {
            byte[] columnFamily = entry.getKey().copyBytesIfNecessary();
            List<Pair<ColumnReference, ColumnReference>> colRefPairs = entry.getValue();
            int maxEncodedColumnQualifier = Integer.MIN_VALUE;
            // find the max col qualifier
            for (Pair<ColumnReference, ColumnReference> colRefPair : colRefPairs) {
                maxEncodedColumnQualifier = Math.max(maxEncodedColumnQualifier, encodingScheme.decode(colRefPair.getFirst().getQualifier()));
            }
            Expression[] colValues = EncodedColumnsUtil.createColumnExpressionArray(maxEncodedColumnQualifier);
            // set the values of the columns
            for (Pair<ColumnReference, ColumnReference> colRefPair : colRefPairs) {
                ColumnReference indexColRef = colRefPair.getFirst();
                ColumnReference dataColRef = colRefPair.getSecond();
                Expression expression = new SingleCellColumnExpression(new PDatum() {

                    @Override
                    public boolean isNullable() {
                        return false;
                    }

                    @Override
                    public SortOrder getSortOrder() {
                        return null;
                    }

                    @Override
                    public Integer getScale() {
                        return null;
                    }

                    @Override
                    public Integer getMaxLength() {
                        return null;
                    }

                    @Override
                    public PDataType getDataType() {
                        return null;
                    }
                }, dataColRef.getFamily(), dataColRef.getQualifier(), encodingScheme);
                ImmutableBytesPtr ptr = new ImmutableBytesPtr();
                expression.evaluate(new ValueGetterTuple(valueGetter), ptr);
                byte[] value = ptr.copyBytesIfNecessary();
                if (value != null) {
                    int indexArrayPos = encodingScheme.decode(indexColRef.getQualifier()) - QueryConstants.ENCODED_CQ_COUNTER_INITIAL_VALUE + 1;
                    colValues[indexArrayPos] = new LiteralExpression(value);
                }
            }
            List<Expression> children = Arrays.asList(colValues);
            // we use SingleCellConstructorExpression to serialize multiple columns into a single byte[]
            SingleCellConstructorExpression singleCellConstructorExpression = new SingleCellConstructorExpression(immutableStorageScheme, children);
            ImmutableBytesWritable ptr = new ImmutableBytesWritable();
            singleCellConstructorExpression.evaluate(new BaseTuple() {
            }, ptr);
            if (put == null) {
                put = new Put(indexRowKey);
                put.setDurability(!indexWALDisabled ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
            }
            ImmutableBytesPtr colFamilyPtr = new ImmutableBytesPtr(columnFamily);
            //this is a little bit of extra work for installations that are running <0.94.14, but that should be rare and is a short-term set of wrappers - it shouldn't kill GC
            put.add(kvBuilder.buildPut(rowKey, colFamilyPtr, QueryConstants.SINGLE_KEYVALUE_COLUMN_QUALIFIER_BYTES_PTR, ts, ptr));
        }
    } else {
        for (ColumnReference ref : this.getCoveredColumns()) {
            ColumnReference indexColRef = this.coveredColumnsMap.get(ref);
            ImmutableBytesPtr cq = indexColRef.getQualifierWritable();
            ImmutableBytesPtr cf = indexColRef.getFamilyWritable();
            ImmutableBytesWritable value = valueGetter.getLatestValue(ref);
            if (value != null) {
                if (put == null) {
                    put = new Put(indexRowKey);
                    put.setDurability(!indexWALDisabled ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
                }
                put.add(kvBuilder.buildPut(rowKey, cf, cq, ts, value));
            }
        }
    }
    return put;
}
Also used : BaseTuple(org.apache.phoenix.schema.tuple.BaseTuple) PDatum(org.apache.phoenix.schema.PDatum) SingleCellConstructorExpression(org.apache.phoenix.expression.SingleCellConstructorExpression) PDataType(org.apache.phoenix.schema.types.PDataType) List(java.util.List) ArrayList(java.util.ArrayList) Pair(org.apache.hadoop.hbase.util.Pair) ImmutableBytesWritable(org.apache.hadoop.hbase.io.ImmutableBytesWritable) ImmutableBytesPtr(org.apache.phoenix.hbase.index.util.ImmutableBytesPtr) LiteralExpression(org.apache.phoenix.expression.LiteralExpression) SortOrder(org.apache.phoenix.schema.SortOrder) Put(org.apache.hadoop.hbase.client.Put) SingleCellColumnExpression(org.apache.phoenix.expression.SingleCellColumnExpression) KeyValueColumnExpression(org.apache.phoenix.expression.KeyValueColumnExpression) SingleCellConstructorExpression(org.apache.phoenix.expression.SingleCellConstructorExpression) Expression(org.apache.phoenix.expression.Expression) SingleCellColumnExpression(org.apache.phoenix.expression.SingleCellColumnExpression) CoerceExpression(org.apache.phoenix.expression.CoerceExpression) LiteralExpression(org.apache.phoenix.expression.LiteralExpression) ColumnReference(org.apache.phoenix.hbase.index.covered.update.ColumnReference) ValueGetterTuple(org.apache.phoenix.schema.tuple.ValueGetterTuple)

Aggregations

ImmutableBytesWritable (org.apache.hadoop.hbase.io.ImmutableBytesWritable)2 CoerceExpression (org.apache.phoenix.expression.CoerceExpression)2 Expression (org.apache.phoenix.expression.Expression)2 KeyValueColumnExpression (org.apache.phoenix.expression.KeyValueColumnExpression)2 LiteralExpression (org.apache.phoenix.expression.LiteralExpression)2 SingleCellColumnExpression (org.apache.phoenix.expression.SingleCellColumnExpression)2 SingleCellConstructorExpression (org.apache.phoenix.expression.SingleCellConstructorExpression)2 SortOrder (org.apache.phoenix.schema.SortOrder)2 ValueGetterTuple (org.apache.phoenix.schema.tuple.ValueGetterTuple)2 PDataType (org.apache.phoenix.schema.types.PDataType)2 DataOutput (java.io.DataOutput)1 DataOutputStream (java.io.DataOutputStream)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Put (org.apache.hadoop.hbase.client.Put)1 Pair (org.apache.hadoop.hbase.util.Pair)1 ColumnReference (org.apache.phoenix.hbase.index.covered.update.ColumnReference)1 ImmutableBytesPtr (org.apache.phoenix.hbase.index.util.ImmutableBytesPtr)1 PDatum (org.apache.phoenix.schema.PDatum)1