org.neo4j.cypher.result.EagerQuerySubscription Maven / Gradle / Ivy
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.cypher.result;
import org.neo4j.graphdb.QueryStatistics;
import org.neo4j.kernel.impl.query.QuerySubscriber;
import org.neo4j.kernel.impl.query.QuerySubscription;
/**
* A query subscription that streams from a materialized result.
*/
public abstract class EagerQuerySubscription implements QuerySubscription {
private long requestedRecords;
private int servedRecords;
protected final QuerySubscriber subscriber;
protected boolean cancelled;
protected Throwable error;
protected EagerQuerySubscription(QuerySubscriber subscriber) {
this.subscriber = subscriber;
}
/**
* Stream one record to the subscriber.
*
* @param servedRecords the number of previously served records
* @throws Exception if the subscriber throws an Exception
*/
protected abstract void streamRecordToSubscriber(int servedRecords) throws Exception;
/**
* @return the statistics of the query execution.
*/
protected abstract QueryStatistics queryStatistics();
/**
* @return the size of the materialized result
*/
protected abstract int resultSize();
/**
* Materialize the result if it has not been materialized yet.
*/
protected abstract void materializeIfNecessary() throws Exception;
@Override
public void request(long numberOfRecords) throws Exception {
requestedRecords = checkForOverflow(requestedRecords + numberOfRecords);
materializeIfNecessary();
streamToSubscriber();
}
@Override
public void cancel() {
cancelled = true;
}
@Override
public boolean await() throws Exception {
boolean hasMore = servedRecords < resultSize();
if (!hasMore) {
if (error != null) {
subscriber.onError(error);
} else {
subscriber.onResultCompleted(queryStatistics());
}
}
return hasMore && !cancelled;
}
private void streamToSubscriber() {
try {
for (; servedRecords < requestedRecords && servedRecords < resultSize(); servedRecords++) {
subscriber.onRecord();
streamRecordToSubscriber(servedRecords);
subscriber.onRecordCompleted();
}
} catch (Throwable t) {
error = t;
servedRecords = resultSize();
}
}
private static long checkForOverflow(long value) {
if (value < 0) {
return Long.MAX_VALUE;
} else {
return value;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy