提交 bc5418e8 编写于 作者: V Vlad Ilyushchenko

GRIFFIN: some record cursors are able to report their size, which will allow...

GRIFFIN: some record cursors are able to report their size, which will allow us to reduce overhead producing HTTP response and also speed up execution of limits and counts
上级 44ce4da2
......@@ -47,4 +47,9 @@ public class FullBwdDataFrameCursor extends AbstractFullDataFrameCursor {
public void toTop() {
this.partitionIndex = this.partitionHi - 1;
}
@Override
public long size() {
return reader.size();
}
}
......@@ -43,6 +43,11 @@ public class FullFwdDataFrameCursor extends AbstractFullDataFrameCursor {
return false;
}
@Override
public long size() {
return reader.size();
}
@Override
public void toTop() {
this.partitionIndex = 0;
......
......@@ -116,6 +116,11 @@ public class IntervalBwdDataFrameCursor extends AbstractIntervalDataFrameCursor
return false;
}
@Override
public long size() {
return -1;
}
@Override
public void toTop() {
super.toTop();
......
......@@ -113,6 +113,11 @@ public class IntervalFwdDataFrameCursor extends AbstractIntervalDataFrameCursor
return false;
}
@Override
public long size() {
return -1;
}
@Override
public void toTop() {
super.toTop();
......
......@@ -244,6 +244,11 @@ public class RecordChain implements Closeable, RecordCursor, Mutable, RecordSink
recordOffset += 8;
}
@Override
public long size() {
return -1;
}
private class RecordChainRecord implements Record {
long fixedOffset;
long baseOffset;
......
......@@ -70,6 +70,11 @@ public class TableReaderRecordCursor implements RecordCursor {
return record;
}
@Override
public long size() {
return reader.size();
}
@Override
public void recordAt(Record record, long rowId) {
((TableReaderRecord) record).jumpTo(Rows.toPartitionIndex(rowId), Rows.toLocalRowID(rowId));
......
......@@ -80,4 +80,9 @@ public class CompactMapCursor implements RecordCursor {
this.nextOffset = 0;
this.offsetHi = offsetHi;
}
@Override
public long size() {
return -1;
}
}
......@@ -143,7 +143,7 @@ public class FastMap implements Map {
this.record = new FastMapRecord(null, 0, keyDataOffset, keyBlockOffset, value, keyTypes);
}
assert this.keyBlockOffset < kLimit - kStart : "page size is too small for number of columns";
this.cursor = new FastMapCursor(record);
this.cursor = new FastMapCursor(record, this);
}
@Override
......
......@@ -29,13 +29,20 @@ import io.questdb.std.Unsafe;
public final class FastMapCursor implements RecordCursor {
private final FastMapRecord record;
private final FastMap map;
private int remaining;
private long address;
private long topAddress;
private int count;
FastMapCursor(FastMapRecord record) {
FastMapCursor(FastMapRecord record, FastMap map) {
this.record = record;
this.map = map;
}
@Override
public long size() {
return map.size();
}
@Override
......
......@@ -41,4 +41,6 @@ public interface DataFrameCursor extends ImmutableIterator<DataFrame>, Closeable
boolean reload();
void toTop();
long size();
}
......@@ -44,4 +44,6 @@ public interface RecordCursor extends Closeable {
void recordAt(long rowId);
void toTop();
long size();
}
......@@ -30,4 +30,6 @@ public interface RowCursorFactory {
default void prepareCursor(TableReader tableReader) {
}
boolean isEntity();
}
......@@ -52,6 +52,7 @@ public abstract class AbstractQueryContext implements Mutable, Closeable {
CharSequence query;
RecordMetadata metadata;
RecordCursor cursor;
long size;
long count;
long skip;
long stop;
......
......@@ -31,13 +31,13 @@ import io.questdb.std.Unsafe;
import java.io.Closeable;
public abstract class AbstractRedBlackTree implements Mutable, Closeable {
// parent is at offset 0
protected static final int O_LEFT = 8;
// P(8) + L + R + C(1) + REF
private static final int BLOCK_SIZE = 8 + 8 + 8 + 1 + 8;
private static final int BLOCK_SIZE = 8 + 8 + 8 + 1 + 8; // 33(it would be good to align to power of two, but entry would use way too much memory)
private static final int O_RIGHT = 16;
private static final int O_COLOUR = 24;
private static final int O_REF = 25;
// private static final int O_TOP = 33;
private static final byte RED = 1;
private static final byte BLACK = 0;
......@@ -76,18 +76,10 @@ public abstract class AbstractRedBlackTree implements Mutable, Closeable {
Unsafe.getUnsafe().putLong(blockAddress + O_RIGHT, right);
}
// protected static long topOf(long blockAddress) {
// return blockAddress == -1 ? -1 : Unsafe.getUnsafe().getLong(blockAddress + O_TOP);
// }
protected static long parentOf(long blockAddress) {
return blockAddress == -1 ? -1 : Unsafe.getUnsafe().getLong(blockAddress);
}
// protected static void setTop(long blockAddress, long recRef) {
// Unsafe.getUnsafe().putLong(blockAddress + O_TOP, recRef);
// }
protected static long parent2Of(long blockAddress) {
return parentOf(parentOf(blockAddress));
}
......@@ -137,6 +129,10 @@ public abstract class AbstractRedBlackTree implements Mutable, Closeable {
return p;
}
public long size() {
return mem.size() / getBlockSize();
}
protected void fix(long x) {
setColor(x, RED);
......
......@@ -51,7 +51,13 @@ final public class EmptyTableRandomRecordCursor implements NoRandomAccessRecordC
public Record newRecord() {
return record;
}
@Override
public void toTop() {
}
@Override
public long size() {
return 0;
}
}
......@@ -50,4 +50,9 @@ final public class EmptyTableRecordCursor implements NoRandomAccessRecordCursor
@Override
public void toTop() {
}
@Override
public long size() {
return 0;
}
}
......@@ -54,6 +54,7 @@ public class LimitRecordCursorFactory extends AbstractRecordCursorFactory {
private final Function hiFunction;
private RecordCursor base;
private long limit;
private long size;
public LimitRecordCursor(Function loFunction, Function hiFunction) {
this.loFunction = loFunction;
......@@ -65,6 +66,14 @@ public class LimitRecordCursorFactory extends AbstractRecordCursorFactory {
base.close();
}
@Override
public long size() {
if (size > -1) {
return size;
}
return -1;
}
@Override
public Record getRecord() {
return base.getRecord();
......@@ -121,9 +130,11 @@ public class LimitRecordCursorFactory extends AbstractRecordCursorFactory {
}
// set limit to return remaining rows
limit = -lo;
size = -lo;
} else if (lo > -1 && hiFunction == null) {
// first N rows
limit = lo;
size = lo;
} else {
// at this stage we have 'hi'
long hi = hiFunction.getLong(null);
......@@ -141,21 +152,26 @@ public class LimitRecordCursorFactory extends AbstractRecordCursorFactory {
// if we asked for -9,-4 but there are 7 records in cursor
// we would first ignore last 4 and return first 3
limit = count + hi;
size = limit;
} else {
skipTo(count + lo);
limit = -lo + hi;
size = limit;
}
}
} else {
// this is invalid bottom range, for example -3, -10
limit = 0;
size = 0;
}
} else {
if (hi < 0) {
limit = countRows() - lo + hi;
size = limit;
base.toTop();
} else {
limit = hi - lo;
size = limit;
}
if (lo > 0 && limit > 0) {
......@@ -166,7 +182,10 @@ public class LimitRecordCursorFactory extends AbstractRecordCursorFactory {
}
private long countRows() {
long count = 0;
long count = base.size();
if (count > -1) {
return count;
}
while (base.hasNext()) {
count++;
}
......
......@@ -136,6 +136,11 @@ public class ClassCatalogueFunctionFactory implements FunctionFactory {
return false;
}
@Override
public long size() {
return -1;
}
@Override
public void toTop() {
if (findFileStruct != 0) {
......
......@@ -84,6 +84,11 @@ public class NamespaceCatalogueFunctionFactory implements FunctionFactory {
public void toTop() {
row = 0;
}
@Override
public long size() {
return 1;
}
}
private static class NamespaceCatalogueRecord implements Record {
......
......@@ -80,6 +80,11 @@ public class LongSequenceFunctionFactory implements FunctionFactory {
public void close() {
}
@Override
public long size() {
return recordCount;
}
@Override
public Record getRecord() {
return record;
......
......@@ -151,5 +151,10 @@ public class DistinctRecordCursorFactory implements RecordCursorFactory {
this.recordSink = recordSink;
this.record = baseCursor.getRecord();
}
@Override
public long size() {
return -1;
}
}
}
......@@ -188,6 +188,11 @@ public class GroupByRecordCursorFactory implements RecordCursorFactory {
return record;
}
@Override
public long size() {
return -1;
}
@Override
public void recordAt(Record record, long atRowId) {
assert record instanceof VirtualRecord;
......
......@@ -73,6 +73,11 @@ class SampleByFillNoneRecordCursor implements DelegatingRecordCursor, NoRandomAc
this.mapCursor = map.getCursor();
}
@Override
public long size() {
return -1;
}
@Override
public void close() {
base.close();
......
......@@ -185,6 +185,11 @@ class SampleByFillPrevRecordCursor implements DelegatingRecordCursor, NoRandomAc
}
}
@Override
public long size() {
return -1;
}
@Override
public void of(RecordCursor base) {
// factory guarantees that base cursor is not empty
......
......@@ -168,6 +168,11 @@ class SampleByFillValueRecordCursor implements DelegatingRecordCursor, NoRandomA
}
}
@Override
public long size() {
return -1;
}
@Override
public void toTop() {
this.base.toTop();
......
......@@ -491,6 +491,11 @@ public class SampleByInterpolateRecordCursorFactory implements RecordCursorFacto
return mapCursor.hasNext();
}
@Override
public long size() {
return mapCursor.size();
}
@Override
public Record newRecord() {
VirtualRecord record = new VirtualRecord(functionRecord.getFunctions());
......
......@@ -43,7 +43,7 @@ public class AsOfJoinLightRecordCursorFactory extends AbstractRecordCursorFactor
private final RecordCursorFactory slaveFactory;
private final RecordSink masterKeySink;
private final RecordSink slaveKeySink;
private final HashJoinRecordCursor cursor;
private final AsOfLightJoinRecordCursor cursor;
public AsOfJoinLightRecordCursorFactory(
CairoConfiguration configuration,
......@@ -63,7 +63,7 @@ public class AsOfJoinLightRecordCursorFactory extends AbstractRecordCursorFactor
joinKeyMap = MapFactory.createMap(configuration, joinColumnTypes, valueTypes);
this.masterKeySink = masterKeySink;
this.slaveKeySink = slaveKeySink;
this.cursor = new HashJoinRecordCursor(
this.cursor = new AsOfLightJoinRecordCursor(
columnSplit,
joinKeyMap,
NullRecordFactory.getInstance(slaveFactory.getMetadata()),
......@@ -94,7 +94,7 @@ public class AsOfJoinLightRecordCursorFactory extends AbstractRecordCursorFactor
return false;
}
private class HashJoinRecordCursor implements NoRandomAccessRecordCursor {
private class AsOfLightJoinRecordCursor implements NoRandomAccessRecordCursor {
private final OuterJoinRecord record;
private final Map joinKeyMap;
private final int columnSplit;
......@@ -107,7 +107,7 @@ public class AsOfJoinLightRecordCursorFactory extends AbstractRecordCursorFactor
private long slaveTimestamp = Long.MIN_VALUE;
private long lastSlaveRowID = Long.MIN_VALUE;
public HashJoinRecordCursor(int columnSplit, Map joinKeyMap, Record nullRecord, int masterTimestampIndex, int slaveTimestampIndex) {
public AsOfLightJoinRecordCursor(int columnSplit, Map joinKeyMap, Record nullRecord, int masterTimestampIndex, int slaveTimestampIndex) {
this.record = new OuterJoinRecord(columnSplit, nullRecord);
this.joinKeyMap = joinKeyMap;
this.columnSplit = columnSplit;
......@@ -134,6 +134,11 @@ public class AsOfJoinLightRecordCursorFactory extends AbstractRecordCursorFactor
return slaveCursor.getSymbolTable(columnIndex - columnSplit);
}
@Override
public long size() {
return -1;
}
@Override
public boolean hasNext() {
......
......@@ -145,6 +145,11 @@ public class AsOfJoinRecordCursorFactory extends AbstractRecordCursorFactory {
return slaveCursor.getSymbolTable(columnIndex - columnSplit);
}
@Override
public long size() {
return -1;
}
@Override
public boolean hasNext() {
......
......@@ -101,6 +101,16 @@ public class CrossJoinRecordCursorFactory extends AbstractRecordCursorFactory {
return slaveCursor.getSymbolTable(columnIndex - columnSplit);
}
@Override
public long size() {
long sizeA = masterCursor.size();
long sizeB = slaveCursor.size();
if (sizeA == -1 || sizeB == -1) {
return -1;
}
return sizeA * sizeB;
}
@Override
public boolean hasNext() {
......
......@@ -145,6 +145,11 @@ public class HashJoinLightRecordCursorFactory extends AbstractRecordCursorFactor
return slaveCursor.getSymbolTable(columnIndex - columnSplit);
}
@Override
public long size() {
return -1;
}
@Override
public boolean hasNext() {
if (slaveChainCursor != null && slaveChainCursor.hasNext()) {
......
......@@ -132,6 +132,11 @@ public class HashJoinRecordCursorFactory extends AbstractRecordCursorFactory {
return slaveCursor.getSymbolTable(columnIndex - columnSplit);
}
@Override
public long size() {
return -1;
}
@Override
public boolean hasNext() {
if (useSlaveCursor && slaveChain.hasNext()) {
......
......@@ -40,7 +40,7 @@ public class HashOuterJoinLightRecordCursorFactory extends AbstractRecordCursorF
private final RecordCursorFactory slaveFactory;
private final RecordSink masterKeySink;
private final RecordSink slaveKeySink;
private final HashJoinRecordCursor cursor;
private final HashOuterJoinLightRecordCursor cursor;
public HashOuterJoinLightRecordCursorFactory(
CairoConfiguration configuration,
......@@ -61,7 +61,7 @@ public class HashOuterJoinLightRecordCursorFactory extends AbstractRecordCursorF
slaveChain = new LongChain(configuration.getSqlHashJoinLightValuePageSize());
this.masterKeySink = masterKeySink;
this.slaveKeySink = slaveKeySink;
this.cursor = new HashJoinRecordCursor(
this.cursor = new HashOuterJoinLightRecordCursor(
columnSplit,
joinKeyMap,
slaveChain,
......@@ -114,7 +114,7 @@ public class HashOuterJoinLightRecordCursorFactory extends AbstractRecordCursorF
}
}
private class HashJoinRecordCursor implements NoRandomAccessRecordCursor {
private class HashOuterJoinLightRecordCursor implements NoRandomAccessRecordCursor {
private final OuterJoinRecord record;
private final LongChain slaveChain;
private final Map joinKeyMap;
......@@ -124,7 +124,7 @@ public class HashOuterJoinLightRecordCursorFactory extends AbstractRecordCursorF
private Record masterRecord;
private LongChain.TreeCursor slaveChainCursor;
public HashJoinRecordCursor(
public HashOuterJoinLightRecordCursor(
int columnSplit,
Map joinKeyMap,
LongChain slaveChain,
......@@ -142,6 +142,11 @@ public class HashOuterJoinLightRecordCursorFactory extends AbstractRecordCursorF
slaveCursor = Misc.free(slaveCursor);
}
@Override
public long size() {
return -1L;
}
@Override
public Record getRecord() {
return record;
......
......@@ -40,7 +40,7 @@ public class HashOuterJoinRecordCursorFactory extends AbstractRecordCursorFactor
private final RecordCursorFactory slaveFactory;
private final RecordSink masterSink;
private final RecordSink slaveKeySink;
private final HashJoinRecordCursor cursor;
private final HashOuterJoinRecordCursor cursor;
public HashOuterJoinRecordCursorFactory(
CairoConfiguration configuration,
......@@ -62,7 +62,7 @@ public class HashOuterJoinRecordCursorFactory extends AbstractRecordCursorFactor
slaveChain = new RecordChain(slaveFactory.getMetadata(), slaveChainSink, configuration.getSqlHashJoinValuePageSize());
this.masterSink = masterSink;
this.slaveKeySink = slaveKeySink;
this.cursor = new HashJoinRecordCursor(
this.cursor = new HashOuterJoinRecordCursor(
columnSplit,
joinKeyMap,
slaveChain,
......@@ -118,7 +118,7 @@ public class HashOuterJoinRecordCursorFactory extends AbstractRecordCursorFactor
buildMap(slaveCursor, slaveCursor.getRecord(), joinKeyMap, slaveKeySink, slaveChain);
}
private class HashJoinRecordCursor implements NoRandomAccessRecordCursor {
private class HashOuterJoinRecordCursor implements NoRandomAccessRecordCursor {
private final OuterJoinRecord record;
private final RecordChain slaveChain;
private final Map joinKeyMap;
......@@ -128,7 +128,7 @@ public class HashOuterJoinRecordCursorFactory extends AbstractRecordCursorFactor
private Record masterRecord;
private boolean useSlaveCursor;
public HashJoinRecordCursor(int columnSplit, Map joinKeyMap, RecordChain slaveChain, Record nullRecord) {
public HashOuterJoinRecordCursor(int columnSplit, Map joinKeyMap, RecordChain slaveChain, Record nullRecord) {
this.record = new OuterJoinRecord(columnSplit, nullRecord);
this.joinKeyMap = joinKeyMap;
this.slaveChain = slaveChain;
......@@ -141,6 +141,11 @@ public class HashOuterJoinRecordCursorFactory extends AbstractRecordCursorFactor
slaveCursor = Misc.free(slaveCursor);
}
@Override
public long size() {
return -1;
}
@Override
public Record getRecord() {
return record;
......
......@@ -61,7 +61,7 @@ public class SpliceJoinLightRecordCursorFactory extends AbstractRecordCursorFact
private final Map joinKeyMap;
private final RecordSink masterKeySink;
private final RecordSink slaveKeySink;
private final FullAslOfJoinCursor cursor;
private final SpliceJoinLightRecordCursor cursor;
public SpliceJoinLightRecordCursorFactory(
CairoConfiguration cairoConfiguration,
......@@ -84,7 +84,7 @@ public class SpliceJoinLightRecordCursorFactory extends AbstractRecordCursorFact
);
this.masterKeySink = masterSink;
this.slaveKeySink = slaveSink;
this.cursor = new FullAslOfJoinCursor(
this.cursor = new SpliceJoinLightRecordCursor(
joinKeyMap,
columnSplit,
masterFactory.getMetadata().getTimestampIndex(),
......@@ -272,7 +272,7 @@ public class SpliceJoinLightRecordCursorFactory extends AbstractRecordCursorFact
}
}
private class FullAslOfJoinCursor implements NoRandomAccessRecordCursor {
private class SpliceJoinLightRecordCursor implements NoRandomAccessRecordCursor {
private final FullJoinRecord record;
private final Map joinKeyMap;
private final int columnSplit;
......@@ -296,7 +296,7 @@ public class SpliceJoinLightRecordCursorFactory extends AbstractRecordCursorFact
private boolean hasSlave = true;
private boolean dualRecord = false;
public FullAslOfJoinCursor(
public SpliceJoinLightRecordCursor(
Map joinKeyMap,
int columnSplit,
int masterTimestampIndex,
......@@ -332,6 +332,11 @@ public class SpliceJoinLightRecordCursorFactory extends AbstractRecordCursorFact
return slaveCursor.getSymbolTable(columnIndex - columnSplit);
}
@Override
public long size() {
return -1L;
}
@Override
public boolean hasNext() {
if (dualRecord) {
......
......@@ -330,6 +330,11 @@ public class RecordTreeChain implements Closeable, Mutable {
return recordChain.hasNext();
}
@Override
public long size() {
return base.size();
}
@Override
public Record newRecord() {
return recordChain.newRecord();
......
......@@ -49,6 +49,11 @@ class SortedLightRecordCursor implements DelegatingRecordCursor {
base.close();
}
@Override
public long size() {
return base.size();
}
@Override
public Record getRecord() {
return baseRecord;
......
......@@ -77,6 +77,11 @@ class SortedRecordCursor implements DelegatingRecordCursor {
chainCursor.toTop();
}
@Override
public long size() {
return chainCursor.size();
}
@Override
public void of(RecordCursor base) {
this.chainCursor = chain.getCursor(base);
......
......@@ -42,6 +42,11 @@ abstract class AbstractTreeSetRecordCursor extends AbstractDataFrameRecordCursor
treeCursor = null;
}
@Override
public long size() {
return treeSet.size();
}
abstract protected void buildTreeMap(SqlExecutionContext executionContext);
@Override
......
......@@ -30,11 +30,13 @@ import org.jetbrains.annotations.Nullable;
class DataFrameRecordCursor extends AbstractDataFrameRecordCursor {
private final RowCursorFactory rowCursorFactory;
private final Function filter;
private final boolean entityCursor;
private RowCursor rowCursor;
public DataFrameRecordCursor(RowCursorFactory rowCursorFactory, @Nullable Function filter) {
public DataFrameRecordCursor(RowCursorFactory rowCursorFactory, @Nullable Function filter, boolean entityCursor) {
this.rowCursorFactory = rowCursorFactory;
this.filter = filter;
this.entityCursor = entityCursor;
}
@Override
......@@ -73,6 +75,11 @@ class DataFrameRecordCursor extends AbstractDataFrameRecordCursor {
}
}
@Override
public long size() {
return entityCursor ? dataFrameCursor.size() : -1;
}
private boolean nextFrame() {
while (dataFrameCursor.hasNext()) {
DataFrame dataFrame = dataFrameCursor.next();
......
......@@ -37,7 +37,7 @@ public class DataFrameRecordCursorFactory extends AbstractDataFrameRecordCursorF
RowCursorFactory rowCursorFactory,
@Nullable Function filter) {
super(metadata, dataFrameCursorFactory);
this.cursor = new DataFrameRecordCursor(rowCursorFactory, filter);
this.cursor = new DataFrameRecordCursor(rowCursorFactory, filter, rowCursorFactory.isEntity());
this.filter = filter;
}
......
......@@ -36,4 +36,8 @@ public class DataFrameRowCursorFactory implements RowCursorFactory {
return cursor;
}
@Override
public boolean isEntity() {
return true;
}
}
......@@ -55,4 +55,9 @@ public class DeferredSymbolIndexFilteredRowCursorFactory implements RowCursorFac
this.cursor.setTableReader(tableReader);
}
}
@Override
public boolean isEntity() {
return false;
}
}
......@@ -63,4 +63,9 @@ public class DeferredSymbolIndexRowCursorFactory implements RowCursorFactory {
this.symbolKey = TableUtils.toIndexKey(symbolKey);
}
}
@Override
public boolean isEntity() {
return false;
}
}
......@@ -60,7 +60,7 @@ public class FilterOnSubQueryRecordCursorFactory extends AbstractDataFrameRecord
this.filter = filter;
this.factories = factoriesA;
cursorFactories = new ObjList<>();
this.cursor = new DataFrameRecordCursor(new HeapRowCursorFactory(cursorFactories), filter);
this.cursor = new DataFrameRecordCursor(new HeapRowCursorFactory(cursorFactories), filter, false);
if (firstColumnType == ColumnType.SYMBOL) {
typeCaster = SymbolTypeCaster.INSTANCE;
} else {
......
......@@ -68,7 +68,7 @@ public class FilterOnValuesRecordCursorFactory extends AbstractDataFrameRecordCu
deferredSymbols.add(Chars.toString(symbol));
}
}
this.cursor = new DataFrameRecordCursor(new HeapRowCursorFactory(cursorFactories), filter);
this.cursor = new DataFrameRecordCursor(new HeapRowCursorFactory(cursorFactories), filter, false);
}
@Override
......
......@@ -63,6 +63,11 @@ class FilteredRecordCursor implements RecordCursor {
return false;
}
@Override
public long size() {
return -1;
}
@Override
public Record newRecord() {
return base.newRecord();
......
......@@ -40,6 +40,11 @@ public class HeapRowCursorFactory implements RowCursorFactory {
this.cursor = new HeapRowCursor();
}
@Override
public boolean isEntity() {
return false;
}
@Override
public RowCursor getCursor(DataFrame dataFrame) {
for (int i = 0, n = cursorFactories.size(); i < n; i++) {
......
......@@ -70,4 +70,9 @@ public class LatestByValueDeferredIndexedRowCursorFactory implements RowCursorFa
}
}
}
@Override
public boolean isEntity() {
return false;
}
}
......@@ -63,6 +63,11 @@ class LatestByValueFilteredRecordCursor extends AbstractDataFrameRecordCursor {
return false;
}
@Override
public long size() {
return -1;
}
@Override
void of(DataFrameCursor dataFrameCursor, SqlExecutionContext executionContext) {
this.dataFrameCursor = dataFrameCursor;
......
......@@ -85,6 +85,11 @@ class LatestByValueIndexedFilteredRecordCursor extends AbstractDataFrameRecordCu
}
}
@Override
public long size() {
return -1;
}
@Override
void of(DataFrameCursor dataFrameCursor, SqlExecutionContext executionContext) {
this.dataFrameCursor = dataFrameCursor;
......
......@@ -55,4 +55,9 @@ public class LatestByValueIndexedRowCursorFactory implements RowCursorFactory {
}
return EmptyRowCursor.INSTANCE;
}
@Override
public boolean isEntity() {
return false;
}
}
......@@ -73,6 +73,11 @@ class LatestByValueRecordCursor extends AbstractDataFrameRecordCursor {
}
}
@Override
public long size() {
return -1;
}
@Override
void of(DataFrameCursor dataFrameCursor, SqlExecutionContext executionContext) {
this.dataFrameCursor = dataFrameCursor;
......
......@@ -53,6 +53,11 @@ class SelectedRecordCursor implements RecordCursor {
return baseCursor.getSymbolTable(columnCrossIndex.getQuick(columnIndex));
}
@Override
public long size() {
return baseCursor.size();
}
@Override
public boolean hasNext() {
return baseCursor.hasNext();
......
......@@ -45,4 +45,9 @@ public class SymbolIndexFilteredRowCursorFactory implements RowCursorFactory {
public void prepareCursor(TableReader tableReader) {
this.cursor.setTableReader(tableReader);
}
@Override
public boolean isEntity() {
return false;
}
}
......@@ -46,4 +46,9 @@ public class SymbolIndexRowCursorFactory implements RowCursorFactory {
.getBitmapIndexReader(columnIndex, BitmapIndexReader.DIR_FORWARD)
.getCursor(cachedIndexReaderCursor, symbolKey, dataFrame.getRowLo(), dataFrame.getRowHi() - 1);
}
@Override
public boolean isEntity() {
return false;
}
}
......@@ -59,6 +59,11 @@ class VirtualRecordCursor implements RecordCursor {
return baseCursor.hasNext();
}
@Override
public long size() {
return baseCursor.size();
}
@Override
public Record newRecord() {
final VirtualRecord record = new VirtualRecord(this.record.getFunctions());
......
......@@ -68,6 +68,16 @@ class UnionAllRecordCursor implements NoRandomAccessRecordCursor {
return slaveCursor.hasNext();
}
@Override
public long size() {
final long masterSize = masterCursor.size();
final long slaveSize = slaveCursor.size();
if (masterSize == -1 || slaveSize == -1) {
return -1;
}
return masterSize + slaveSize;
}
@Override
public SymbolTable getSymbolTable(int columnIndex) {
return symbolCursor.getSymbolTable(columnIndex);
......
......@@ -125,6 +125,11 @@ class UnionRecordCursor implements NoRandomAccessRecordCursor {
slaveCursor.toTop();
}
@Override
public long size() {
return -1;
}
interface NextMethod {
boolean next();
}
......
......@@ -128,9 +128,15 @@ public class AbstractGriffinTest extends AbstractCairoTest {
Assert.assertNotNull(record);
sink.clear();
printer.printHeader(metadata);
long count = 0;
long cursorSize = cursor.size();
while (cursor.hasNext()) {
printer.print(record, metadata);
count++;
}
Assert.assertTrue(cursorSize == -1 || count == cursorSize);
TestUtils.assertEquals(expected, sink);
if (supportsRandomAccess) {
......
......@@ -39,6 +39,11 @@ class RandomRecordCursor implements NoRandomAccessRecordCursor {
recordIndex = 0;
}
@Override
public long size() {
return recordCount;
}
@Override
public void close() {
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册