Java Code Examples for org.apache.phoenix.util.SchemaUtil#getSeparatorByte()

The following examples show how to use org.apache.phoenix.util.SchemaUtil#getSeparatorByte() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: BaseResultIterators.java    From phoenix with Apache License 2.0 5 votes vote down vote up
private static boolean clipKeyRangeBytes(RowKeySchema schema, int fieldIndex, int rangeSpan, byte[] rowKey, ImmutableBytesWritable ptr, boolean trimTrailingNulls) {
    int position = 0;
    int maxOffset = schema.iterator(rowKey, ptr);
    byte[] newRowKey = new byte[rowKey.length];
    int offset = 0;
    int trailingNullsToTrim = 0;
    do {
        if (schema.next(ptr, fieldIndex, maxOffset) == null) {
            break;
        }
        System.arraycopy(ptr.get(), ptr.getOffset(), newRowKey, offset, ptr.getLength());
        offset += ptr.getLength();
        Field field =  schema.getField(fieldIndex);
        if (field.getDataType().isFixedWidth()) {
            trailingNullsToTrim = 0;
        } else {
            boolean isNull = ptr.getLength() == 0;
            byte sepByte = SchemaUtil.getSeparatorByte(true, isNull, field);
            newRowKey[offset++] = sepByte;
            if (isNull) {
                if (trimTrailingNulls) {
                    trailingNullsToTrim++;
                } else {
                    trailingNullsToTrim = 0;
                }
            } else {
                // So that last zero separator byte is always trimmed
                trailingNullsToTrim = 1;
            }
        }
        fieldIndex++;
    } while (++position < rangeSpan);
    // remove trailing nulls
    ptr.set(newRowKey, 0, offset - trailingNullsToTrim);
    // return true if we've clipped the rowKey
    return maxOffset != offset;
}
 
Example 2
Source File: SkipScanFilter.java    From phoenix with Apache License 2.0 5 votes vote down vote up
private int setStartKey(ImmutableBytesWritable ptr, int offset, int i, int nSlots, boolean atEndOfKey) {
    int length = ptr.getOffset() - offset;
    startKey = copyKey(startKey, length + this.maxKeyLength, ptr.get(), offset, length);
    startKeyLength = length;
    // Add separator byte if we're at end of the key, since trailing separator bytes are stripped
    if (atEndOfKey && i > 0 && i-1 < nSlots) {
        Field field = schema.getField(i-1);
        if (!field.getDataType().isFixedWidth()) {
            startKey[startKeyLength++] = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), true, field);
        }
    }
    startKeyLength += setKey(Bound.LOWER, startKey, startKeyLength, i);
    return length;
}
 
Example 3
Source File: ScanRanges.java    From phoenix with Apache License 2.0 4 votes vote down vote up
public static ScanRanges create(RowKeySchema schema, List<List<KeyRange>> ranges, int[] slotSpan, Integer nBuckets, boolean useSkipScan, int rowTimestampColIndex, Optional<byte[]> scanMinOffset) {
    int offset = nBuckets == null ? 0 : SaltingUtil.NUM_SALTING_BYTES;
    int nSlots = ranges.size();

    if (nSlots == offset && !scanMinOffset.isPresent()) {
        return EVERYTHING;
    } else if ((nSlots == 1 + offset && ranges.get(offset).size() == 1 && ranges.get(offset).get(0) == KeyRange.EMPTY_RANGE)) {
        return NOTHING;
    }
    TimeRange rowTimestampRange = getRowTimestampColumnRange(ranges, schema, rowTimestampColIndex);
    boolean isPointLookup = isPointLookup(schema, ranges, slotSpan, useSkipScan);
    if (isPointLookup) {
        // TODO: consider keeping original to use for serialization as it would be smaller?
        List<byte[]> keys = ScanRanges.getPointKeys(ranges, slotSpan, schema, nBuckets);
        List<KeyRange> keyRanges = Lists.newArrayListWithExpectedSize(keys.size());
        // We have full keys here, so use field from our varbinary schema
        for (byte[] key : keys) {
            keyRanges.add(KeyRange.getKeyRange(key));
        }
        // while doing a point look up if after intersecting with the MinMaxrange there are
        // no more keyranges left then just return
        if (keyRanges.isEmpty()) {
            return NOTHING;
        }
        ranges = Collections.singletonList(keyRanges);
        useSkipScan = keyRanges.size() > 1;
        // Treat as binary if descending because we've got a separator byte at the end
        // which is not part of the value.
        if (keys.size() > 1 || SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), false, schema.getField(schema.getFieldCount()-1)) == QueryConstants.DESC_SEPARATOR_BYTE) {
            schema = SchemaUtil.VAR_BINARY_SCHEMA;
            slotSpan = ScanUtil.SINGLE_COLUMN_SLOT_SPAN;
        } else {
            // Keep original schema and don't use skip scan as it's not necessary
            // when there's a single key.
            slotSpan = new int[] {schema.getMaxFields()-1};
        }
    }

    List<List<KeyRange>> sortedRanges = Lists.newArrayListWithExpectedSize(ranges.size());
    for (int i = 0; i < ranges.size(); i++) {
        Field f = schema.getField(i);
        List<KeyRange> sorted = Lists.newArrayList(ranges.get(i));
        Collections.sort(sorted, f.getSortOrder() == SortOrder.ASC ? KeyRange.COMPARATOR : KeyRange.DESC_COMPARATOR);
        sortedRanges.add(ImmutableList.copyOf(sorted));
    }
    
    
    // Don't set minMaxRange for point lookup because it causes issues during intersect
    // by going across region boundaries
    KeyRange scanRange = KeyRange.EVERYTHING_RANGE;
    // if (!isPointLookup && (nBuckets == null || !useSkipScanFilter)) {
    // if (! ( isPointLookup || (nBuckets != null && useSkipScanFilter) ) ) {
    // if (nBuckets == null || (nBuckets != null && (!isPointLookup || !useSkipScanFilter))) {
    if (nBuckets == null || !isPointLookup || !useSkipScan) {
        byte[] minKey = ScanUtil.getMinKey(schema, sortedRanges, slotSpan);
        byte[] maxKey = ScanUtil.getMaxKey(schema, sortedRanges, slotSpan);
        // If the maxKey has crossed the salt byte boundary, then we do not
        // have anything to filter at the upper end of the range
        if (ScanUtil.crossesPrefixBoundary(maxKey, ScanUtil.getPrefix(minKey, offset), offset)) {
            maxKey = KeyRange.UNBOUND;
        }
        // We won't filter anything at the low end of the range if we just have the salt byte
        if (minKey.length <= offset) {
            minKey = KeyRange.UNBOUND;
        }

        //Handle the offset by pushing it into the scanRange
        if(scanMinOffset.isPresent()){

            byte[] minOffset = scanMinOffset.get();
            //If we are salted we have to
            //This should be safe for RVC Offset since we specify a full rowkey which
            // is by definition unique so duplicating the salt bucket is fine
            if(nBuckets != null && nBuckets > 0) {
                minOffset[0] = 0;  //We use 0 for salt bucket for scans
            }

            //If the offset is more selective than the existing ranges
            if(Bytes.BYTES_COMPARATOR.compare(minOffset,minKey) > 0){
                minKey=minOffset;
            }
        }

        scanRange = KeyRange.getKeyRange(minKey, maxKey);
    }

    if (scanRange == KeyRange.EMPTY_RANGE) {
        return NOTHING;
    }
    return new ScanRanges(schema, slotSpan, sortedRanges, scanRange, useSkipScan, isPointLookup, nBuckets, rowTimestampRange);
}
 
Example 4
Source File: RowValueConstructorExpression.java    From phoenix with Apache License 2.0 4 votes vote down vote up
@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if(literalExprPtr != null) {
        // if determined during construction that the row value constructor is just comprised of literal expressions, 
        // let's just return the ptr we have already computed and be done with evaluation.
        ptr.set(literalExprPtr.get(), literalExprPtr.getOffset(), literalExprPtr.getLength());
        return true;
    }
    try {
        boolean isPartialEval = this.partialEvalIndex >= 0;
        int evalIndex = isPartialEval ? this.partialEvalIndex : 0;
        int expressionCount = evalIndex;
        for(; evalIndex < ptrs.length; evalIndex++) {
            final Expression expression = children.get(evalIndex);
            // TODO: handle overflow and underflow
            if (expression.evaluate(tuple, ptr)) {
                if (ptr.getLength() == 0) {
                    estimatedByteSize += getExpressionByteCount(expression);
                } else {
                    expressionCount = evalIndex+1;
                    ptrs[evalIndex] = new ImmutableBytesWritable();
                    ptrs[evalIndex].set(ptr.get(), ptr.getOffset(), ptr.getLength());
                    estimatedByteSize += ptr.getLength() + (expression.getDataType().isFixedWidth() ? 0 : 1); // 1 extra for the separator byte.
                }
            } else if (tuple == null || tuple.isImmutable()) {
                estimatedByteSize += getExpressionByteCount(expression);
            } else { // Cannot yet be evaluated
                return false;
            }
        }
        if (isPartialEval) {
            this.partialEvalIndex = evalIndex; // Move counter forward
        }
        
        if (evalIndex == ptrs.length) {
            if (expressionCount == 0) {
                ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
                return true;
            }
            if (expressionCount == 1) {
                ptr.set(ptrs[0].get(), ptrs[0].getOffset(), ptrs[0].getLength());
                return true;
            }
            TrustedByteArrayOutputStream output = new TrustedByteArrayOutputStream(estimatedByteSize);
            try {
                boolean previousCarryOver = false;
                for (int i = 0; i< expressionCount; i++) {
                    Expression child = getChildren().get(i);
                    PDataType childType = child.getDataType();
                    ImmutableBytesWritable tempPtr = ptrs[i];
                    if (tempPtr == null) {
                        // Since we have a null and have no representation for null,
                        // we must decrement the value of the current. Otherwise,
                        // we'd have an ambiguity if this value happened to be the
                        // min possible value.
                        previousCarryOver = childType == null || childType.isFixedWidth();
                        int bytesToWrite = getExpressionByteCount(child);
                        for (int m = 0; m < bytesToWrite; m++) {
                            output.write(QueryConstants.SEPARATOR_BYTE);
                        }
                    } else {
                        output.write(tempPtr.get(), tempPtr.getOffset(), tempPtr.getLength());
                        if (!childType.isFixedWidth()) {
                            output.write(SchemaUtil.getSeparatorByte(true, false, child));
                        }
                        if (previousCarryOver) {
                            previousCarryOver = !ByteUtil.previousKey(output.getBuffer(), output.size());
                        }
                    }
                }
                int outputSize = output.size();
                byte[] outputBytes = output.getBuffer();
                // Don't remove trailing separator byte unless it's the one for ASC
                // as otherwise we need it to ensure sort order is correct.
                // Additionally for b/w compat with clients older than 4.14.1 -
                // If SortOorder.ASC then always strip trailing separator byte (as before)
                // else only strip for >= 4.14 client (when STRIP_TRAILING_SEPARATOR_BYTE bit is set)
                for (int k = expressionCount -1 ; 
                        k >=0 &&  getChildren().get(k).getDataType() != null 
                              && !getChildren().get(k).getDataType().isFixedWidth()
                              && outputBytes[outputSize-1] == SchemaUtil.getSeparatorByte(true, false, getChildren().get(k))
                              &&  (getChildren().get(k).getSortOrder() == SortOrder.ASC ? true : isStripTrailingSepByte()) ; k--) {
                    outputSize--;
                }
                ptr.set(outputBytes, 0, outputSize);
                return true;
            } finally {
                output.close();
            }
        }  
        return false;
    } catch (IOException e) {
        throw new RuntimeException(e); //Impossible.
    }
}
 
Example 5
Source File: PArrayDataType.java    From phoenix with Apache License 2.0 4 votes vote down vote up
public static byte getSeparatorByte(boolean rowKeyOrderOptimizable, SortOrder sortOrder) {
    return SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, sortOrder);
}
 
Example 6
Source File: RowKeySchema.java    From phoenix with Apache License 2.0 4 votes vote down vote up
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
        value="NP_BOOLEAN_RETURN_NULL", 
        justification="Designed to return null.")
private Boolean next(ImmutableBytesWritable ptr, int position, int maxOffset, boolean isFirst) {
    if (ptr.getOffset() + ptr.getLength() >= maxOffset) {
        ptr.set(ptr.get(), maxOffset, 0);
        return null;
    }
    if (position >= getFieldCount()) {
        return null;
    }
    // Move the pointer past the current value and set length
    // to 0 to ensure you never set the ptr past the end of the
    // backing byte array.
    ptr.set(ptr.get(), ptr.getOffset() + ptr.getLength(), 0);
    // If positioned at SEPARATOR_BYTE, skip it.
    // Don't look back at previous fields if this is our first next call, as
    // we may have a partial key for RVCs that doesn't include the leading field.
    if (position > 0 && !isFirst && !getField(position-1).getDataType().isFixedWidth()) {
        ptr.set(ptr.get(), ptr.getOffset()+ptr.getLength()+1, 0);
    }
    Field field = this.getField(position);
    if (field.getDataType().isFixedWidth()) {
        // It is possible that the number of remaining row key bytes are less than the fixed
        // width size. See PHOENIX-3968.
        ptr.set(ptr.get(), ptr.getOffset(), Math.min(maxOffset - ptr.getOffset(), field.getByteSize()));
    } else {
        if (position+1 == getFieldCount() ) {
            // Last field has no terminator unless it's descending sort order
            int len = maxOffset - ptr.getOffset();
            ptr.set(ptr.get(), ptr.getOffset(), maxOffset - ptr.getOffset() - (SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, len == 0, field) == QueryConstants.DESC_SEPARATOR_BYTE ? 1 : 0));
        } else {
            byte[] buf = ptr.get();
            int offset = ptr.getOffset();
            // First byte 
            if (offset < maxOffset && buf[offset] != QueryConstants.SEPARATOR_BYTE) {
                byte sepByte = SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, field);
                do {
                    offset++;
                } while (offset < maxOffset && buf[offset] != sepByte);
            }
            ptr.set(buf, ptr.getOffset(), offset - ptr.getOffset());
        }
    }
    return ptr.getLength() > 0;
}
 
Example 7
Source File: RowKeySchema.java    From phoenix with Apache License 2.0 4 votes vote down vote up
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
        value="NP_BOOLEAN_RETURN_NULL", 
        justification="Designed to return null.")
public Boolean previous(ImmutableBytesWritable ptr, int position, int minOffset) {
    if (position < 0) {
        return null;
    }
    Field field = this.getField(position);
    if (field.getDataType().isFixedWidth()) {
        ptr.set(ptr.get(), ptr.getOffset()-field.getByteSize(), field.getByteSize());
        return true;
    }
    // If ptr has length of zero, it is assumed that we're at the end of the row key
    int offsetAdjustment = position + 1 == this.getFieldCount() || ptr.getLength() == 0 ? 0 : 1;
    if (position == 0) {
        ptr.set(ptr.get(), minOffset, ptr.getOffset() - minOffset - offsetAdjustment);
        return true;
    }
    field = this.getField(position-1);
    // Field before the one we want to position at is variable length
    // In this case, we can search backwards for our separator byte
    // to determine the length
    if (!field.getDataType().isFixedWidth()) {
        byte[] buf = ptr.get();
        int offset = ptr.getOffset()-1-offsetAdjustment;
        // Separator always zero byte if zero length
        if (offset > minOffset && buf[offset] != QueryConstants.SEPARATOR_BYTE) {
            byte sepByte = SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, field);
            do {
                offset--;
            } while (offset > minOffset && buf[offset] != sepByte);
        }
        if (offset == minOffset) { // shouldn't happen
            ptr.set(buf, minOffset, ptr.getOffset()-minOffset-1);
        } else {
            ptr.set(buf,offset+1,ptr.getOffset()-1-offsetAdjustment-offset); // Don't include null terminator in length
        }
        return true;
    }
    int i,fixedOffset = field.getByteSize();
    for (i = position-2; i >= 0 && this.getField(i).getDataType().isFixedWidth(); i--) {
        fixedOffset += this.getField(i).getByteSize();
    }
    // All of the previous fields are fixed width, so we can calculate the offset
    // based on the total fixed offset
    if (i < 0) {
        int length = ptr.getOffset() - fixedOffset - minOffset - offsetAdjustment;
        ptr.set(ptr.get(),minOffset+fixedOffset, length);
        return true;
    }
    // Otherwise we're stuck with starting from the minOffset and working all the way forward,
    // because we can't infer the length of the previous position.
    return iterator(ptr.get(), minOffset, ptr.getOffset() - minOffset - offsetAdjustment, ptr, position+1);
}