== Cursors and streaming

By default prepared query execution fetches all rows, you can use a
`link:../../jsdoc/module-vertx-sql-client-js_cursor-Cursor.html[Cursor]` to control the amount of rows you want to read:

[source,js]
----
var Tuple = require("vertx-sql-client-js/tuple");
connection.prepare("SELECT * FROM users WHERE age > ?", function (ar1, ar1_err) {
  if (ar1_err == null) {
    var pq = ar1;

    // Create a cursor
    var cursor = pq.cursor(Tuple.of(18));

    // Read 50 rows
    cursor.read(50, function (ar2, ar2_err) {
      if (ar2_err == null) {
        var rows = ar2;

        // Check for more ?
        if (cursor.hasMore()) {
          // Repeat the process...
        } else {
          // No more rows - close the cursor
          cursor.close();
        }
      }
    });
  }
});

----

PostreSQL destroys cursors at the end of a transaction, so the cursor API shall be used
within a transaction, otherwise you will likely get the `34000` PostgreSQL error.

Cursors shall be closed when they are released prematurely:

[source,js]
----
cursor.read(50, function (ar2, ar2_err) {
  if (ar2_err == null) {
    // Close the cursor
    cursor.close();
  }
});

----

A stream API is also available for cursors, which can be more convenient, specially with the Rxified version.

[source,js]
----
var Tuple = require("vertx-sql-client-js/tuple");
connection.prepare("SELECT * FROM users WHERE age > ?", function (ar1, ar1_err) {
  if (ar1_err == null) {
    var pq = ar1;

    // Fetch 50 rows at a time
    var stream = pq.createStream(50, Tuple.of(18));

    // Use the stream
    stream.exceptionHandler(function (err) {
      console.log("Error: " + err.getMessage());
    });
    stream.endHandler(function (v) {
      console.log("End of stream");
    });
    stream.handler(function (row) {
      console.log("User: " + row.getString("last_name"));
    });
  }
});

----

The stream read the rows by batch of `50` and stream them, when the rows have been passed to the handler,
a new batch of `50` is read and so on.

The stream can be resumed or paused, the loaded rows will remain in memory until they are delivered and the cursor
will stop iterating.