// Given the splits and the rowKeySchema, find out the keys that public static byte[][] processSplits( byte[][] splits, LinkedHashSet<PColumn> pkColumns, Integer saltBucketNum, boolean defaultRowKeyOrder) throws SQLException { // FIXME: shouldn't this return if splits.length == 0? if (splits == null) return null; // We do not accept user specified splits if the table is salted and we specify // defaultRowKeyOrder. In this case, // throw an exception. if (splits.length > 0 && saltBucketNum != null && defaultRowKeyOrder) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_SPLITS_ON_SALTED_TABLE) .build() .buildException(); } // If the splits are not specified and table is salted, pre-split the table. if (splits.length == 0 && saltBucketNum != null) { splits = SaltingUtil.getSalteByteSplitPoints(saltBucketNum); } byte[][] newSplits = new byte[splits.length][]; for (int i = 0; i < splits.length; i++) { newSplits[i] = processSplit(splits[i], pkColumns); } return newSplits; }
private static List<byte[]> getPointKeys( List<List<KeyRange>> ranges, int[] slotSpan, RowKeySchema schema, Integer bucketNum) { if (ranges == null || ranges.isEmpty()) { return Collections.emptyList(); } boolean isSalted = bucketNum != null; int count = 1; int offset = isSalted ? 1 : 0; // Skip salt byte range in the first position if salted for (int i = offset; i < ranges.size(); i++) { count *= ranges.get(i).size(); } List<byte[]> keys = Lists.newArrayListWithExpectedSize(count); int[] position = new int[ranges.size()]; int maxKeyLength = SchemaUtil.getMaxKeyLength(schema, ranges); int length; byte[] key = new byte[maxKeyLength]; do { length = ScanUtil.setKey( schema, ranges, slotSpan, position, Bound.LOWER, key, offset, offset, ranges.size(), offset); if (isSalted) { key[0] = SaltingUtil.getSaltingByte(key, offset, length, bucketNum); } keys.add(Arrays.copyOf(key, length + offset)); } while (incrementKey(ranges, position)); return keys; }
private ScanRanges( RowKeySchema schema, int[] slotSpan, List<List<KeyRange>> ranges, KeyRange scanRange, KeyRange minMaxRange, boolean useSkipScanFilter, boolean isPointLookup, Integer bucketNum, TimeRange rowTimestampRange) { this.isPointLookup = isPointLookup; this.isSalted = bucketNum != null; this.useSkipScanFilter = useSkipScanFilter; this.scanRange = scanRange; this.minMaxRange = minMaxRange; this.rowTimestampRange = rowTimestampRange; // Only blow out the bucket values if we're using the skip scan. We need all the // bucket values in this case because we use intersect against a key that may have // any of the possible bucket values. Otherwise, we can pretty easily ignore the // bucket values. if (useSkipScanFilter && isSalted && !isPointLookup) { ranges.set(0, SaltingUtil.generateAllSaltingRanges(bucketNum)); } this.ranges = ImmutableList.copyOf(ranges); this.slotSpan = slotSpan; this.schema = schema; if (schema != null && !ranges.isEmpty()) { if (!this.useSkipScanFilter) { int boundSlotCount = this.getBoundSlotCount(); ranges = ranges.subList(0, boundSlotCount); slotSpan = Arrays.copyOf(slotSpan, boundSlotCount); } this.filter = new SkipScanFilter(ranges, slotSpan, this.schema); } }