node-postgres/lib/native/query.js

109 lines
2.8 KiB
JavaScript
Raw Normal View History

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');
2014-10-18 12:27:28 +08:00
var NativeResult = require('./result');
2011-08-30 12:06:07 +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';
this._arrayMode = false;
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));
};
util.inherits(NativeQuery, EventEmitter);
2014-09-15 09:11:51 +08:00
NativeQuery.prototype.handleError = function(err) {
var self = this;
//copy pq error fields into the error object
var fields = self.native.pq.resultErrorFields();
if(fields) {
for(var key in fields) {
err[key] = fields[key];
}
}
if(self.callback) {
self.callback(err);
} else {
self.emit('error', err);
}
self.state = 'error';
2014-10-10 09:12:17 +08:00
};
2014-09-15 09:11:51 +08:00
NativeQuery.prototype.submit = function(client) {
this.state = 'running';
var self = this;
client.native.arrayMode = this._arrayMode;
var after = function(err, rows) {
client.native.arrayMode = false;
2014-09-14 10:37:30 +08:00
setImmediate(function() {
self.emit('_done');
});
//handle possible query error
if(err) {
2014-09-15 09:11:51 +08:00
return self.handleError(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
//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);
if(self.callback) {
2014-09-14 13:23:02 +08:00
self.callback(null, result);
}
2014-10-10 09:12:17 +08:00
};
2014-09-15 09:11:51 +08:00
if(process.domain) {
after = process.domain.bind(after);
}
//named query
if(this.name) {
var values = (this.values||[]).map(utils.prepareValue);
//check if the client has already executed this named query
//if so...just execute it again - skip the planning phase
if(client.namedQueries[this.name]) {
return this.native.execute(this.name, values, after);
}
//plan the named query the first time, then execute it
return this.native.prepare(this.name, this.text, values.length, function(err) {
if(err) return after(err);
2014-09-15 09:11:51 +08:00
client.namedQueries[self.name] = true;
return self.native.execute(self.name, values, after);
2014-10-10 09:12:17 +08:00
});
2014-09-15 09:11:51 +08:00
}
else if(this.values) {
2014-10-10 09:12:17 +08:00
var vals = this.values.map(utils.prepareValue);
this.native.query(this.text, vals, after);
} else {
this.native.query(this.text, after);
}
};