All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.driver.dse.graph.GraphResultSet Maven / Gradle / Ivy

Go to download

A driver for DataStax Enterprise (DSE) and Apache Cassandra 1.2+ clusters that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol, supporting DSE-specific features such as geospatial types, DSE Graph and DSE authentication.

There is a newer version: 2.4.0
Show newest version
/*
 * Copyright (C) 2012-2017 DataStax Inc.
 *
 * This software can be used solely with DataStax Enterprise. Please consult the license at
 * http://www.datastax.com/terms/datastax-dse-driver-license-terms
 */
package com.datastax.driver.dse.graph;

import com.datastax.driver.core.ExecutionInfo;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.exceptions.DriverException;
import com.datastax.driver.dse.DseSession;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import java.util.Iterator;
import java.util.List;

/**
 * The result of a graph query.
 */
public class GraphResultSet implements Iterable {

    static final Function ROW_TO_DEFAULTGRAPHNODE = new Function() {

        @Override
        public GraphNode apply(Row row) {
            // Seems like sometimes traversals can return empty rows
            if (row != null) {
                String jsonString = row.getString("gremlin");
                try {
                    return GraphJsonUtils.readStringAsTree(jsonString);
                } catch (RuntimeException e) {
                    throw new DriverException("Could not parse the result returned by the Graph server as a JSON string : " + jsonString, e);
                }
            } else {
                return null;
            }
        }
    };

    private long bulk = 0;
    private GraphNode lastGraphNode = null;

    private final ResultSet wrapped;
    private final Function transformResultFunction;

    /**
     * This constructor is intended for internal use only, users should normally obtain instances from
     * {@link DseSession#executeGraph(GraphStatement)}.
     */
    public GraphResultSet(ResultSet wrapped) {
        this(wrapped, ROW_TO_DEFAULTGRAPHNODE);
    }

    public GraphResultSet(ResultSet wrapped, Function transformResultFunction) {
        this.wrapped = wrapped;
        this.transformResultFunction = transformResultFunction;
    }

    /**
     * Returns whether there are more results.
     *
     * @return whether there are more results.
     */
    public boolean isExhausted() {
        return wrapped.isExhausted() && bulk <= 1;
    }

    /**
     * Returns the next result.
     *
     * @return the next result, or {@code null} if there are no more of them.
     */
    public GraphNode one() {
        if (bulk > 1) {
            bulk--;
            // TODO: return a copy? Not sure it's useful because the content of this is supposed to be immutable.
            return lastGraphNode;
        }
        GraphNode container = this.transformResultFunction.apply(wrapped.one());

        if (container == null) {
            return null;
        }

        if (container.get(GraphSONTokens.BULK) != null) {
            bulk = container.get(GraphSONTokens.BULK).asLong();
        }

        GraphNode results = container.get("result");
        lastGraphNode = results;
        return results;
    }

    /**
     * Returns all the remaining results as a list.
     *
     * @return a list containing the remaining results. The result set will be exhausted after a call to this method.
     */
    public List all() {
        return ImmutableList.copyOf(iterator());
    }

    /**
     * Returns an iterator over the results.
     * 

* The {@link Iterator#next} method is equivalent to calling {@link #one}. After a full iteration, the result set * will be exhausted. *

* The returned iterator does not support the {@link Iterator#remove} method. * * @return an iterator that will consume and return the remaining results. */ public Iterator iterator() { return new Iterator() { @Override public boolean hasNext() { return !isExhausted(); } @Override public GraphNode next() { return one(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * This method has been deprecated because it may return incorrect numbers. Since paging * is not implemented in DSE Graph, using {@link #all()} is recommended instead to gather all * the results coming back from a DSE Graph query. *

* The number of results that can be retrieved without blocking to fetch. * * @return the number of results readily available. If {@link #isFullyFetched()}, this is the total number of * results remaining, otherwise going past that limit will trigger background fetches. */ @Deprecated public int getAvailableWithoutFetching() { return wrapped.getAvailableWithoutFetching(); } /** * This method has been deprecated because paging is not implemented for DSE Graph. *

* Whether all results have been fetched from the database. *

* If {@code isFullyFetched()}, then {@link #getAvailableWithoutFetching} will return the number of results * remaining before exhaustion. *

* But {@code !isFullyFetched()} does not necessarily mean that the result set is not exhausted (you should call * {@code isExhausted()} to verify it). * * @return whether all results have been fetched. */ @Deprecated public boolean isFullyFetched() { return wrapped.isFullyFetched(); } /** * This method has been deprecated because paging is not implemented for DSE Graph. *

* Force fetching the next page of results for this result set, if any. *

* This method is entirely optional. It will be called automatically while * the result set is consumed (through {@link #one}, {@link #all} or iteration) * when needed (i.e. when {@code getAvailableWithoutFetching() == 0} and * {@code isFullyFetched() == false}). *

* You can however call this method manually to force the fetching of the * next page of results. This can allow to prefetch results before they are * strictly needed. For instance, if you want to prefetch the next page of * results as soon as there is less than 100 rows readily available in this * result set, you can do: *

     *   GraphResultSet rs = session.executeGraph(...);
     *   Iterator<GraphNode> iter = rs.iterator();
     *   while (iter.hasNext()) {
     *       if (rs.getAvailableWithoutFetching() == 100 && !rs.isFullyFetched())
     *           rs.fetchMoreResults();
     *       GraphNode result = iter.next()
     *       ... process the result ...
     *   }
     * 
* This method is not blocking, so in the example above, the call to {@code * fetchMoreResults} will not block the processing of the 100 currently available * results (but {@code iter.hasNext()} will block once those results have been processed * until the fetch query returns, if it hasn't yet). *

* Only one page of results (for a given result set) can be * fetched at any given time. If this method is called twice and the query * triggered by the first call has not returned yet when the second one is * performed, then the 2nd call will simply return a future on the currently * in progress query. * * @return a future on the completion of fetching the next page of results. * If the result set is already fully retrieved ({@code isFullyFetched() == true}), * then the returned future will return immediately, but not particular error will be * thrown (you should thus call {@code isFullyFetched() to know if calling this * method can be of any use}). */ @Deprecated public ListenableFuture fetchMoreResults() { return Futures.transform(wrapped.fetchMoreResults(), new Function() { @Override public GraphResultSet apply(ResultSet input) { return new GraphResultSet(input, transformResultFunction); } }); } /** * Returns information on the execution of the last query made for this result set. *

* Note that in most cases, a result set is fetched with only one query, but large * result sets can be paged and thus be retrieved by multiple queries. In that * case this method return the {@code ExecutionInfo} for the last query * performed. To retrieve the information for all queries, use {@link #getAllExecutionInfo}. *

* The returned object includes basic information such as the queried hosts, * but also the Cassandra query trace if tracing was enabled for the query. * * @return the execution info for the last query made for this GraphResultSet. */ public ExecutionInfo getExecutionInfo() { return wrapped.getExecutionInfo(); } /** * Returns the execution information for all queries made to retrieve this result set. *

* If paging was used, the returned list contains the {@code ExecutionInfo} for all the queries done to obtain the * results (at the time of the call), in the order those queries were made. *

* If no paging was used (because the result set was small enough), the list only contains one element. * * @return a list of the execution info for all the queries made for this GraphResultSet. */ public List getAllExecutionInfo() { return wrapped.getAllExecutionInfo(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy