public static WhereClauses create(String tableIdentifier, RangeRequest request, String... clauses) { List<String> extraWhereClauses = Lists.newArrayList(clauses); byte[] start = request.getStartInclusive(); byte[] end = request.getEndExclusive(); Collection<byte[]> cols = request.getColumnNames(); List<Object> args = Lists.newArrayListWithCapacity(2 + cols.size()); List<String> whereClauses = Lists.newArrayListWithCapacity(3 + extraWhereClauses.size()); if (start.length > 0) { whereClauses.add(tableIdentifier + (request.isReverse() ? ".row_name <= ?" : ".row_name >= ?")); args.add(start); } if (end.length > 0) { whereClauses.add(tableIdentifier + (request.isReverse() ? ".row_name > ?" : ".row_name < ?")); args.add(end); } if (!cols.isEmpty()) { whereClauses.add(tableIdentifier + ".col_name IN (" + BasicSQLUtils.nArguments(cols.size()) + ")"); args.addAll(cols); } whereClauses.addAll(extraWhereClauses); return new WhereClauses(whereClauses, args); }
@Override public FullQuery getRangeQuery(RangeRequest range, long ts, int maxRows) { List<String> bounds = Lists.newArrayListWithCapacity(2); List<Object> args = Lists.newArrayListWithCapacity(2); byte[] start = range.getStartInclusive(); byte[] end = range.getEndExclusive(); if (start.length > 0) { bounds.add(range.isReverse() ? "m.row_name <= ?" : "m.row_name >= ?"); args.add(start); } if (end.length > 0) { bounds.add(range.isReverse() ? "m.row_name > ?" : "m.row_name < ?"); args.add(end); } String query = " /* GET_RANGE_ROWS (" + tableName + ") */ " + " SELECT DISTINCT m.row_name " + " FROM " + prefixedTableName() + " m " + (bounds.isEmpty() ? "" : " WHERE " + Joiner.on(" AND ").join(bounds)) + " ORDER BY m.row_name " + (range.isReverse() ? "DESC" : "ASC") + " LIMIT " + maxRows; return new FullQuery(query).withArgs(args); }
@Override public ClosableIterator<RowResult<Value>> getRange( TableReference tableRef, final RangeRequest range, final long timestamp) { boolean reversed = range.isReverse(); return getRangeInternal(tableRef, range, entries -> { Entry<Key, byte[]> lastEntry = null; while (entries.hasNext()) { Entry<Key, byte[]> entry = entries.next(); if (reversed && entry.getKey().ts < timestamp) { lastEntry = entry; break; } else if (!reversed && entry.getKey().ts >= timestamp) { break; } lastEntry = entry; } if (lastEntry != null) { long ts = lastEntry.getKey().ts; return Value.createWithCopyOfData(lastEntry.getValue(), ts); } else { return null; } }); }
/** * This is a replacement for startRow when doing reverse range request. */ public static byte[] startRowInclusiveOrLargestRow(RangeRequest rangeRequest) { Preconditions.checkArgument(rangeRequest.isReverse()); if (rangeRequest.getStartInclusive().length == 0) { return getLastRowName(); } return rangeRequest.getStartInclusive(); }
/** * This is a replacement for endRow when doing a non-reverse range request. */ public static byte[] endRowExclusiveOrOneAfterMax(RangeRequest rangeRequest) { Preconditions.checkArgument(!rangeRequest.isReverse()); if (rangeRequest.getEndExclusive().length == 0) { return oneAfterMaximumName(); } return rangeRequest.getEndExclusive(); }
byte[] end = range.getEndExclusive(); if (start.length > 0) { bounds.add(range.isReverse() ? "m.row_name <= ?" : "m.row_name >= ?"); args.add(start); bounds.add(range.isReverse() ? "m.row_name > ?" : "m.row_name < ?"); args.add(end); String query = " /* GET_RANGE_ONE_ROW (" + tableName + ") */ " + " SELECT /*+ INDEX(m " + PrimaryKeyConstraintNames.get(tableName) + ") */ " + (range.isReverse() ? "max" : "min") + "(m.row_name) as row_name " + " FROM " + tableName + " m " + (bounds.isEmpty() ? "" : " WHERE " + Joiner.on(" AND ").join(bounds)); + " FROM " + tableName + " m " + (bounds.isEmpty() ? "" : " WHERE " + Joiner.on(" AND ").join(bounds)) + " ORDER BY m.row_name " + (range.isReverse() ? "DESC" : "ASC") + " ) inner WHERE rownum <= " + maxRows; return new FullQuery(query).withArgs(args);
private List<Entry<Cell, byte[]>> getPostFilteredWithLocalWrites(final TableReference tableRef, final SortedMap<Cell, byte[]> postFiltered, final RangeRequest rangeRequest, List<RowResult<Value>> prePostFilter, final byte[] endRowExclusive) { Map<Cell, Value> prePostFilterCells = Cells.convertRowResultsToCells(prePostFilter); Collection<Entry<Cell, byte[]>> postFilteredCells = Collections2.filter( postFiltered.entrySet(), Predicates.compose( Predicates.in(prePostFilterCells.keySet()), MapEntries.getKeyFunction())); Collection<Entry<Cell, byte[]>> localWritesInRange = getLocalWritesForRange( tableRef, rangeRequest.getStartInclusive(), endRowExclusive).entrySet(); return mergeInLocalWrites( tableRef, postFilteredCells.iterator(), localWritesInRange.iterator(), rangeRequest.isReverse()); }
private Map<RangeRequest, TokenBackedBasicResultsPage<RowResult<Value>, byte[]>> getFirstPages( TableReference tableRef, List<RangeRequest> requests, long timestamp) { List<String> subQueries = Lists.newArrayList(); List<Object> argsList = Lists.newArrayList(); for (int i = 0; i < requests.size(); i++) { RangeRequest request = requests.get(i); Pair<String, List<Object>> queryAndArgs = getRangeQueryAndArgs( tableRef, request.getStartInclusive(), request.getEndExclusive(), request.isReverse(), request.getBatchHint() == null ? 1 : request.getBatchHint(), i); subQueries.add(queryAndArgs.lhSide); argsList.addAll(queryAndArgs.rhSide); } String query = Joiner.on(") UNION ALL (").appendTo(new StringBuilder("("), subQueries).append(")").toString(); Object[] args = argsList.toArray(); TimingState timer = logTimer.begin("Table: " + tableRef.getQualifiedName() + " get_page"); try { return getFirstPagesFromDb(tableRef, requests, timestamp, query, args); } finally { timer.end(); } }
request.isReverse() ? cellsByRow.descendingMap() : cellsByRow, Predicates.in(rowNames)); request.getStartInclusive(), request.getEndExclusive(), request.isReverse()); } else { byte[] last = rowNames.last(); if (request.isReverse()) { last = rowNames.first(); if (RangeRequests.isTerminalRow(request.isReverse(), last)) { ret.put(request, SimpleTokenBackedResultsPage.create(last, rows, false)); } else { byte[] nextStartRow = RangeRequests.getNextStartRow(request.isReverse(), last); ret.put(request, SimpleTokenBackedResultsPage.create(nextStartRow, rows, hasMore));
private void verifyRanges(Transaction readOnlyTransaction) { // verify each set of reads to ensure they are the same. for (Entry<TableReference, ConcurrentMap<RangeRequest, byte[]>> tableAndRange : rangeEndByTable.entrySet()) { TableReference table = tableAndRange.getKey(); Map<RangeRequest, byte[]> rangeEnds = tableAndRange.getValue(); for (Entry<RangeRequest, byte[]> rangeAndRangeEndEntry : rangeEnds.entrySet()) { RangeRequest range = rangeAndRangeEndEntry.getKey(); byte[] rangeEnd = rangeAndRangeEndEntry.getValue(); if (rangeEnd.length != 0 && !RangeRequests.isTerminalRow(range.isReverse(), rangeEnd)) { range = range.getBuilder() .endRowExclusive(RangeRequests.getNextStartRow(range.isReverse(), rangeEnd)) .build(); } ConcurrentNavigableMap<Cell, byte[]> writes = writesByTable.get(table); BatchingVisitableView<RowResult<byte[]>> bv = BatchingVisitableView.of( readOnlyTransaction.getRange(table, range)); NavigableMap<Cell, ByteBuffer> readsInRange = Maps.transformValues( getReadsInRange(table, range), ByteBuffer::wrap); if (!bv.transformBatch(input -> filterWritesFromRows(input, writes)).isEqual(readsInRange.entrySet())) { handleTransactionConflict(table); } } } }
private <T> ClosableIterator<RowResult<T>> getRangeWithPageCreator( RowGetter rowGetter, SlicePredicate slicePredicate, ColumnGetter columnGetter, RangeRequest rangeRequest, Supplier<ResultsExtractor<T>> resultsExtractor, long startTs) { if (rangeRequest.isReverse()) { throw new UnsupportedOperationException(); } if (rangeRequest.isEmptyRange()) { return ClosableIterators.wrap(ImmutableList.<RowResult<T>>of().iterator()); } CassandraRangePagingIterable<T> rowResults = new CassandraRangePagingIterable<>( rowGetter, slicePredicate, columnGetter, rangeRequest, resultsExtractor, startTs ); return ClosableIterators.wrap(rowResults.iterator()); } }
@Override public ClosableIterator<RowResult<Value>> getBatch(int batchSize, @Nullable byte[] lastToken) { RangeRequest.Builder newRange = range.getBuilder(); if (lastToken != null) { newRange.startRowInclusive(RangeRequests.getNextStartRow(range.isReverse(), lastToken)); } newRange.batchHint(batchSize); return keyValueService.getRange(tableRef, newRange.build(), timestamp); }
if (rangeRequest.isReverse()) { valuesByRow = valuesByRow.descendingMap(); boolean mayHaveMoreResults = false; byte[] lastRow = Iterables.getLast(finalResults).getRowName(); if (!RangeRequests.isTerminalRow(rangeRequest.isReverse(), lastRow)) { nextRow = RangeRequests.getNextStartRow(rangeRequest.isReverse(), lastRow); mayHaveMoreResults = finalResults.size() == maxRows;
@Override public Iterator<RowResult<Value>> getRange(TableReference tableRef, RangeRequest rangeRequest, long timestamp) { boolean haveOverflow = checkIfTableHasOverflowUsingNewConnection(tableRef); return Iterators.concat(new PageIterator( rangeRequest.getStartInclusive(), rangeRequest.getEndExclusive(), rangeRequest.getColumnNames(), rangeRequest.isReverse(), tableRef, haveOverflow, RangeHelpers.getMaxRowsPerPage(rangeRequest), timestamp)); }
if (RangeRequests.isTerminalRow(request.isReverse(), lastRowName)) { ret.put(request, SimpleTokenBackedResultsPage.create(lastRowName, results, false)); return; byte[] nextStartRow = RangeRequests.getNextStartRow(request.isReverse(), lastRowName); if (Arrays.equals(request.getEndExclusive(), nextStartRow)) { ret.put(request, SimpleTokenBackedResultsPage.create(nextStartRow, results, false));
@Override public Iterator<RowResult<Value>> getRange(TableReference tableRef, RangeRequest rangeRequest, long timestamp) { int maxRowsPerPage = RangeHelpers.getMaxRowsPerPage(rangeRequest); int cellsPerRowEstimate = getCellsPerRowEstimate(tableRef, rangeRequest); int maxCellsPerPage = Math.min( AtlasDbPerformanceConstants.MAX_BATCH_SIZE, maxRowsPerPage * cellsPerRowEstimate) + 1; String tableName = DbKvs.internalTableName(tableRef); Iterator<Iterator<RowResult<Value>>> pageIterator = new PageIterator( rangeRequest.getStartInclusive(), rangeRequest.getEndExclusive(), rangeRequest.getColumnNames(), rangeRequest.isReverse(), timestamp, maxRowsPerPage, maxCellsPerPage, tableName, prefixedTableNames.get(tableRef)); return Iterators.concat(pageIterator); }
private <K extends Exception> boolean getBatchingVisitableFromIterator( TableReference tableRef, RangeRequest range, int userRequestedSize, AbortingVisitor<List<RowResult<byte[]>>, K> visitor, int preFilterBatchSize) throws K { ClosableIterator<RowResult<byte[]>> postFilterIterator = postFilterIterator(tableRef, range, preFilterBatchSize, Value.GET_VALUE); try { Iterator<RowResult<byte[]>> localWritesInRange = Cells.createRowView( getLocalWritesForRange(tableRef, range.getStartInclusive(), range.getEndExclusive()).entrySet()); Iterator<RowResult<byte[]>> mergeIterators = mergeInLocalWritesRows(postFilterIterator, localWritesInRange, range.isReverse()); return BatchingVisitableFromIterable.create(mergeIterators).batchAccept(userRequestedSize, visitor); } finally { postFilterIterator.close(); } }
private SelectOffsetStep<Record1<byte[]>> getRangeQuery(DSLContext ctx, TableReference tableRef, RangeRequest rangeRequest, long timestamp, int maxRows) { boolean reverse = rangeRequest.isReverse(); byte[] start = rangeRequest.getStartInclusive(); byte[] end = rangeRequest.getEndExclusive(); Condition cond = R_TIMESTAMP.lessThan(timestamp); if (start.length > 0) { cond = cond.and(reverse ? R_ROW_NAME.lessOrEqual(start) : R_ROW_NAME.greaterOrEqual(start)); } if (end.length > 0) { cond = cond.and(reverse ? R_ROW_NAME.greaterThan(end) : R_ROW_NAME.lessThan(end)); } return ctx.selectDistinct(R_ROW_NAME) .from(atlasTable(tableRef).as(RANGE_TABLE)) .where(cond) .orderBy(reverse ? R_ROW_NAME.desc() : R_ROW_NAME.asc()) .limit(maxRows); }