include command metadata with native query result callback - closes #128
This commit is contained in:
parent
7f00b3ee30
commit
176e6c7ab2
@ -132,6 +132,14 @@ var clientBuilder = function(config) {
|
|||||||
connection._activeQuery.handleRow(row);
|
connection._activeQuery.handleRow(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connection.on('_cmdStatus', function(status) {
|
||||||
|
var meta = {
|
||||||
|
};
|
||||||
|
meta.command = status.command.split(' ')[0];
|
||||||
|
meta.rowCount = parseInt(status.value);
|
||||||
|
connection._lastMeta = meta;
|
||||||
|
});
|
||||||
|
|
||||||
//TODO: emit more native error properties (make it match js error)
|
//TODO: emit more native error properties (make it match js error)
|
||||||
connection.on('_error', function(err) {
|
connection.on('_error', function(err) {
|
||||||
//create Error object from object literal
|
//create Error object from object literal
|
||||||
@ -156,7 +164,7 @@ var clientBuilder = function(config) {
|
|||||||
this._namedQuery = false;
|
this._namedQuery = false;
|
||||||
this._sendQueryPrepared(q.name, q.values||[]);
|
this._sendQueryPrepared(q.name, q.values||[]);
|
||||||
} else {
|
} else {
|
||||||
connection._activeQuery.handleReadyForQuery();
|
connection._activeQuery.handleReadyForQuery(connection._lastMeta);
|
||||||
connection._activeQuery = null;
|
connection._activeQuery = null;
|
||||||
connection._pulseQueryQueue();
|
connection._pulseQueryQueue();
|
||||||
}
|
}
|
||||||
|
@ -82,9 +82,10 @@ p.handleError = function(error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.handleReadyForQuery = function() {
|
p.handleReadyForQuery = function(meta) {
|
||||||
if(this.callback) {
|
if(this.callback) {
|
||||||
this.callback(null, { rows: this.rows });
|
(meta || {}).rows = this.rows;
|
||||||
|
this.callback(null, meta);
|
||||||
}
|
}
|
||||||
this.emit('end');
|
this.emit('end');
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,7 @@ static Persistent<String> type_symbol;
|
|||||||
static Persistent<String> channel_symbol;
|
static Persistent<String> channel_symbol;
|
||||||
static Persistent<String> payload_symbol;
|
static Persistent<String> payload_symbol;
|
||||||
static Persistent<String> emit_symbol;
|
static Persistent<String> emit_symbol;
|
||||||
|
static Persistent<String> command_symbol;
|
||||||
|
|
||||||
class Connection : public ObjectWrap {
|
class Connection : public ObjectWrap {
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ public:
|
|||||||
type_symbol = NODE_PSYMBOL("type");
|
type_symbol = NODE_PSYMBOL("type");
|
||||||
channel_symbol = NODE_PSYMBOL("channel");
|
channel_symbol = NODE_PSYMBOL("channel");
|
||||||
payload_symbol = NODE_PSYMBOL("payload");
|
payload_symbol = NODE_PSYMBOL("payload");
|
||||||
|
command_symbol = NODE_PSYMBOL("command");
|
||||||
|
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
|
NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
|
||||||
@ -437,19 +439,22 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleResult(const PGresult* result)
|
void HandleResult(PGresult* result)
|
||||||
{
|
{
|
||||||
ExecStatusType status = PQresultStatus(result);
|
ExecStatusType status = PQresultStatus(result);
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case PGRES_TUPLES_OK:
|
case PGRES_TUPLES_OK:
|
||||||
HandleTuplesResult(result);
|
{
|
||||||
|
HandleTuplesResult(result);
|
||||||
|
EmitCommandMetaData(result);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PGRES_FATAL_ERROR:
|
case PGRES_FATAL_ERROR:
|
||||||
HandleErrorResult(result);
|
HandleErrorResult(result);
|
||||||
break;
|
break;
|
||||||
case PGRES_COMMAND_OK:
|
case PGRES_COMMAND_OK:
|
||||||
case PGRES_EMPTY_QUERY:
|
case PGRES_EMPTY_QUERY:
|
||||||
//do nothing
|
EmitCommandMetaData(result);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unrecogized query status: %s\n", PQresStatus(status));
|
printf("Unrecogized query status: %s\n", PQresStatus(status));
|
||||||
@ -457,12 +462,23 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitCommandMetaData(PGresult* result)
|
||||||
|
{
|
||||||
|
HandleScope scope;
|
||||||
|
Local<Object> info = Object::New();
|
||||||
|
info->Set(command_symbol, String::New(PQcmdStatus(result)));
|
||||||
|
info->Set(value_symbol, String::New(PQcmdTuples(result)));
|
||||||
|
Handle<Value> e = (Handle<Value>)info;
|
||||||
|
Emit("_cmdStatus", &e);
|
||||||
|
}
|
||||||
|
|
||||||
//maps the postgres tuple results to v8 objects
|
//maps the postgres tuple results to v8 objects
|
||||||
//and emits row events
|
//and emits row events
|
||||||
//TODO look at emitting fewer events because the back & forth between
|
//TODO look at emitting fewer events because the back & forth between
|
||||||
//javascript & c++ might introduce overhead (requires benchmarking)
|
//javascript & c++ might introduce overhead (requires benchmarking)
|
||||||
void HandleTuplesResult(const PGresult* result)
|
void HandleTuplesResult(const PGresult* result)
|
||||||
{
|
{
|
||||||
|
HandleScope scope;
|
||||||
int rowCount = PQntuples(result);
|
int rowCount = PQntuples(result);
|
||||||
for(int rowNumber = 0; rowNumber < rowCount; rowNumber++) {
|
for(int rowNumber = 0; rowNumber < rowCount; rowNumber++) {
|
||||||
//create result object for this row
|
//create result object for this row
|
||||||
@ -489,7 +505,6 @@ protected:
|
|||||||
row->Set(Integer::New(fieldNumber), field);
|
row->Set(Integer::New(fieldNumber), field);
|
||||||
}
|
}
|
||||||
|
|
||||||
//not sure about what to dealloc or scope#Close here
|
|
||||||
Handle<Value> e = (Handle<Value>)row;
|
Handle<Value> e = (Handle<Value>)row;
|
||||||
Emit("_row", &e);
|
Emit("_row", &e);
|
||||||
}
|
}
|
||||||
@ -564,30 +579,30 @@ private:
|
|||||||
{
|
{
|
||||||
PostgresPollingStatusType status = PQconnectPoll(connection_);
|
PostgresPollingStatusType status = PQconnectPoll(connection_);
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case PGRES_POLLING_READING:
|
case PGRES_POLLING_READING:
|
||||||
TRACE("Polled: PGRES_POLLING_READING");
|
TRACE("Polled: PGRES_POLLING_READING");
|
||||||
StopWrite();
|
StopWrite();
|
||||||
StartRead();
|
StartRead();
|
||||||
break;
|
break;
|
||||||
case PGRES_POLLING_WRITING:
|
case PGRES_POLLING_WRITING:
|
||||||
TRACE("Polled: PGRES_POLLING_WRITING");
|
TRACE("Polled: PGRES_POLLING_WRITING");
|
||||||
StopRead();
|
StopRead();
|
||||||
StartWrite();
|
StartWrite();
|
||||||
break;
|
break;
|
||||||
case PGRES_POLLING_FAILED:
|
case PGRES_POLLING_FAILED:
|
||||||
StopRead();
|
StopRead();
|
||||||
StopWrite();
|
StopWrite();
|
||||||
TRACE("Polled: PGRES_POLLING_FAILED");
|
TRACE("Polled: PGRES_POLLING_FAILED");
|
||||||
EmitLastError();
|
EmitLastError();
|
||||||
break;
|
break;
|
||||||
case PGRES_POLLING_OK:
|
case PGRES_POLLING_OK:
|
||||||
TRACE("Polled: PGRES_POLLING_OK");
|
TRACE("Polled: PGRES_POLLING_OK");
|
||||||
connecting_ = false;
|
connecting_ = false;
|
||||||
StartRead();
|
StartRead();
|
||||||
Emit("connect");
|
Emit("connect");
|
||||||
default:
|
default:
|
||||||
//printf("Unknown polling status: %d\n", status);
|
//printf("Unknown polling status: %d\n", status);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,25 +2,21 @@ var helper = require(__dirname + "/test-helper");
|
|||||||
var pg = helper.pg;
|
var pg = helper.pg;
|
||||||
|
|
||||||
test('should return insert metadata', function() {
|
test('should return insert metadata', function() {
|
||||||
return false;
|
|
||||||
pg.connect(helper.config, assert.calls(function(err, client) {
|
pg.connect(helper.config, assert.calls(function(err, client) {
|
||||||
assert.isNull(err);
|
assert.isNull(err);
|
||||||
client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) {
|
client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) {
|
||||||
assert.isNull(err);
|
assert.isNull(err);
|
||||||
//let's list this as ignored for now
|
|
||||||
// process.nextTick(function() {
|
|
||||||
// test('should identify "CREATE TABLE" message', function() {
|
|
||||||
// return false;
|
|
||||||
// assert.equal(result.command, "CREATE TABLE");
|
|
||||||
// assert.equal(result.rowCount, 0);
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
assert.equal(result.oid, null);
|
assert.equal(result.oid, null);
|
||||||
|
assert.equal(result.command, 'CREATE');
|
||||||
client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function(err, result) {
|
client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function(err, result) {
|
||||||
assert.equal(result.command, "INSERT");
|
assert.equal(result.command, "INSERT");
|
||||||
assert.equal(result.rowCount, 1);
|
assert.equal(result.rowCount, 1);
|
||||||
process.nextTick(client.end.bind(client));
|
client.query('SELECT * FROM zugzug', assert.calls(function(err, result) {
|
||||||
return false;
|
assert.isNull(err);
|
||||||
|
assert.equal(result.rowCount, 1);
|
||||||
|
assert.equal(result.command, 'SELECT');
|
||||||
|
process.nextTick(pg.end.bind(pg));
|
||||||
|
}))
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
|
Loading…
Reference in New Issue
Block a user