diff --git a/.travis.yml b/.travis.yml index 061e3d15..267b07b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,13 @@ language: node_js +dist: trusty +sudo: false node_js: - - "0.10" - - "0.11" + - "6" env: - PGUSER=postgres +services: + - postgresql +addons: + postgresql: "9.6" +before_script: + - psql -c 'create database travis;' -U postgres | true \ No newline at end of file diff --git a/README.md b/README.md index 1cddfbfd..fe79bf74 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,13 @@ pg.connect(function(err, client, done) { Creates an instance of a query cursor. Pass this instance to node-postgres [`client#query`](https://github.com/brianc/node-postgres/wiki/Client#wiki-method-query-parameterized) -#### cursor#read(int rowCount, function callback(Error err, Array rows) +#### cursor#read(int rowCount, function callback(Error err, Array rows, Result result) Read `rowCount` rows from the cursor instance. The `callback` will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types. If the cursor has read to the end of the result sets all subsequent calls to `cursor#read` will return a 0 length array of rows. I'm open to other ways to signal the end of a cursor, but this has worked out well for me so far. +`result` is a special [https://github.com/brianc/node-postgres/wiki/Query#result-object](Result) object that can be used to accumulate rows. #### cursor#close(function callback(Error err)) diff --git a/index.js b/index.js index 70a90f57..0827043e 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,11 @@ var Result = require('./pg').Result var prepare = require('./pg').prepareValue +var EventEmitter = require('events').EventEmitter; +var util = require('util'); + +function Cursor (text, values) { + EventEmitter.call(this); -var Cursor = function(text, values) { this.text = text this.values = values ? values.map(prepare) : null this.connection = null @@ -12,6 +16,8 @@ var Cursor = function(text, values) { this._rows = null } +util.inherits(Cursor, EventEmitter) + Cursor.prototype.submit = function(connection) { this.connection = connection @@ -58,6 +64,7 @@ Cursor.prototype.handleRowDescription = function(msg) { Cursor.prototype.handleDataRow = function(msg) { var row = this._result.parseRow(msg.fields) + this.emit('row', row, this._result) this._rows.push(row) } @@ -70,7 +77,8 @@ Cursor.prototype._sendRows = function() { //within the call to this callback this._cb = null if(cb) { - cb(null, this._rows) + this._result.rows = this._rows + cb(null, this._rows, this._result) } this._rows = [] }.bind(this)) @@ -86,6 +94,7 @@ Cursor.prototype.handlePortalSuspended = function() { Cursor.prototype.handleReadyForQuery = function() { this._sendRows() + this.emit('end', this._result) this.state = 'done' } @@ -106,6 +115,11 @@ Cursor.prototype.handleError = function(msg) { for(var i = 0; i < this._queue.length; i++) { this._queue.pop()[1](msg) } + + if (this.eventNames().indexOf('error') >= 0) { + //only dispatch error events if we have a listener + this.emit('error', msg) + } //call sync to keep this connection from hanging this.connection.sync() } diff --git a/package.json b/package.json index 1096dee9..f3a0d642 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.0.0", + "version": "1.2.0", "description": "", "main": "index.js", "directories": { diff --git a/pg.js b/pg.js index 96cd7f9a..c6be9ba6 100644 --- a/pg.js +++ b/pg.js @@ -1,13 +1,10 @@ -var path = require('path') -var pgPath; //support both pg & pg.js //this will eventually go away when i break native bindings //out into their own module try { - pgPath = path.dirname(require.resolve('pg')) + module.exports.Result = require('pg/lib/result.js') + module.exports.prepareValue = require('pg/lib/utils.js').prepareValue } catch(e) { - pgPath = path.dirname(require.resolve('pg.js')) + '/lib' + module.exports.Result = require('pg.js/lib/result.js') + module.exports.prepareValue = require('pg.js/lib/utils.js').prepareValue } - -module.exports.Result = require(path.join(pgPath, 'result.js')) -module.exports.prepareValue = require(path.join(pgPath, 'utils.js')).prepareValue diff --git a/test/index.js b/test/index.js index 8f04ccc2..cc97960e 100644 --- a/test/index.js +++ b/test/index.js @@ -116,4 +116,44 @@ describe('cursor', function() { }) }) }) + + it('returns result along with rows', function(done) { + var cursor = this.pgCursor(text) + cursor.read(1, function(err, rows, result) { + assert.ifError(err) + assert.equal(rows.length, 1) + assert.strictEqual(rows, result.rows) + assert.deepEqual(result.fields.map(f => f.name), ['num']) + done() + }) + }) + + it('emits row events', function(done) { + var cursor = this.pgCursor(text) + cursor.read(10) + cursor.on('row', (row, result) => result.addRow(row)) + cursor.on('end', (result) => { + assert.equal(result.rows.length, 6) + done() + }) + }) + + it('emits row events when cursor is closed manually', function(done) { + var cursor = this.pgCursor(text) + cursor.on('row', (row, result) => result.addRow(row)) + cursor.on('end', (result) => { + assert.equal(result.rows.length, 3) + done() + }) + + cursor.read(3, () => cursor.close()) + }) + + it('emits error events', function(done) { + var cursor = this.pgCursor('select asdfasdf') + cursor.on('error', function(err) { + assert(err) + done() + }) + }) })