2011-08-30 12:06:07 +08:00
|
|
|
var EventEmitter = require('events').EventEmitter;
|
2011-10-11 08:40:52 +08:00
|
|
|
var util = require('util');
|
2014-09-14 13:23:02 +08:00
|
|
|
var utils = require('../utils');
|
2011-08-30 12:06:07 +08:00
|
|
|
|
2014-09-14 00:32:53 +08:00
|
|
|
var NativeQuery = module.exports = function(native) {
|
|
|
|
EventEmitter.call(this);
|
|
|
|
this.native = native;
|
|
|
|
this.text = null;
|
|
|
|
this.values = null;
|
|
|
|
this.name = null;
|
|
|
|
this.callback = null;
|
|
|
|
this.state = 'new';
|
2014-09-14 10:37:30 +08:00
|
|
|
|
|
|
|
//if the 'row' event is listened for
|
|
|
|
//then emit them as they come in
|
|
|
|
//without setting singleRowMode to true
|
|
|
|
//this has almost no meaning because libpq
|
|
|
|
//reads all rows into memory befor returning any
|
|
|
|
this._emitRowEvents = false;
|
2014-09-14 13:23:02 +08:00
|
|
|
this.on('newListener', function(event) {
|
2014-09-14 10:37:30 +08:00
|
|
|
if(event === 'row') this._emitRowEvents = true;
|
|
|
|
}.bind(this));
|
2014-09-14 00:32:53 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
util.inherits(NativeQuery, EventEmitter);
|
|
|
|
|
2014-09-14 13:23:02 +08:00
|
|
|
//given an array of values, turn all `undefined` into `null`
|
|
|
|
var clean = function(values) {
|
|
|
|
for(var i = 0; i < values.length; i++) {
|
|
|
|
if(typeof values[i] == 'undefined') {
|
|
|
|
values[i] = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var NativeResult = function(pq) {
|
|
|
|
this.command = null;
|
|
|
|
this.rowCount = 0;
|
|
|
|
this.rows = null;
|
|
|
|
this.fields = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
NativeResult.prototype.addCommandComplete = function(pq) {
|
|
|
|
this.command = pq.cmdStatus().split(' ')[0];
|
|
|
|
this.rowCount = pq.cmdTuples();
|
|
|
|
var nfields = pq.nfields();
|
|
|
|
if(nfields < 1) return;
|
|
|
|
|
|
|
|
this.fields = [];
|
|
|
|
for(var i = 0; i < nfields; i++) {
|
|
|
|
this.fields.push({
|
|
|
|
name: pq.fname(i),
|
|
|
|
dataTypeID: pq.ftype(i)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-14 00:32:53 +08:00
|
|
|
NativeQuery.prototype.submit = function() {
|
|
|
|
this.state = 'running';
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
var after = function(err, rows) {
|
2014-09-14 10:37:30 +08:00
|
|
|
setImmediate(function() {
|
|
|
|
self.emit('_done');
|
|
|
|
});
|
2014-09-14 00:32:53 +08:00
|
|
|
|
|
|
|
//handle possible query error
|
|
|
|
if(err) {
|
|
|
|
self.state = 'error';
|
|
|
|
if(self.callback) return self.callback(err);
|
|
|
|
return self.emit('error', err);
|
|
|
|
}
|
|
|
|
|
2014-09-14 13:23:02 +08:00
|
|
|
var result = new NativeResult();
|
|
|
|
result.addCommandComplete(self.native.pq);
|
|
|
|
result.rows = rows;
|
|
|
|
|
2014-09-14 10:37:30 +08:00
|
|
|
//emit row events for each row in the result
|
|
|
|
if(self._emitRowEvents) {
|
2014-09-14 13:23:02 +08:00
|
|
|
rows.forEach(function(row) {
|
|
|
|
self.emit('row', row, result);
|
|
|
|
});
|
2014-09-14 10:37:30 +08:00
|
|
|
}
|
|
|
|
|
2014-09-14 13:23:02 +08:00
|
|
|
|
2014-09-14 00:32:53 +08:00
|
|
|
//handle successful result
|
2014-09-14 10:37:30 +08:00
|
|
|
self.state = 'end';
|
2014-09-14 13:23:02 +08:00
|
|
|
self.emit('end', result);
|
2014-09-14 00:32:53 +08:00
|
|
|
if(self.callback) {
|
2014-09-14 13:23:02 +08:00
|
|
|
self.callback(null, result);
|
2014-09-14 00:32:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(this.values) {
|
2014-09-14 13:23:02 +08:00
|
|
|
var values = this.values.map(utils.prepareValue);
|
|
|
|
this.native.query(this.text, values, after);
|
2014-09-14 00:32:53 +08:00
|
|
|
} else {
|
|
|
|
this.native.query(this.text, after);
|
|
|
|
}
|
|
|
|
};
|