Skip to content

Commit

Permalink
Merge pull request #679 from whitelynx/master
Browse files Browse the repository at this point in the history
Added per-client type parser overrides.
  • Loading branch information
brianc committed Dec 4, 2014
2 parents e2ea482 + 4bfdc04 commit d3b47a9
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 2 deletions.
12 changes: 12 additions & 0 deletions lib/client.js
Expand Up @@ -2,6 +2,7 @@ var crypto = require('crypto');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var pgPass = require('pgpass');
var TypeOverrides = require('./type-overrides');

var ConnectionParameters = require(__dirname + '/connection-parameters');
var Query = require(__dirname + '/query');
Expand All @@ -20,6 +21,8 @@ var Client = function(config) {

var c = config || {};

this._types = new TypeOverrides(c.types);

this.connection = c.connection || new Connection({
stream: c.stream,
ssl: this.connectionParameters.ssl
Expand Down Expand Up @@ -227,6 +230,14 @@ Client.prototype.cancel = function(client, query) {
}
};

Client.prototype.setTypeParser = function(oid, format, parseFn) {
return this._types.setTypeParser(oid, format, parseFn);
};

Client.prototype.getTypeParser = function(oid, format) {
return this._types.getTypeParser(oid, format);
};

// Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c
Client.prototype.escapeIdentifier = function(str) {

Expand Down Expand Up @@ -302,6 +313,7 @@ Client.prototype.query = function(config, values, callback) {
if(this.binary && !query.binary) {
query.binary = true;
}
query._result._getTypeParser = this._types.getTypeParser.bind(this._types);

this.queryQueue.push(query);
this._pulseQueryQueue();
Expand Down
13 changes: 12 additions & 1 deletion lib/native/index.js
@@ -1,4 +1,5 @@
var Native = require('pg-native');
var TypeOverrides = require('../type-overrides');
var semver = require('semver');
var pkg = require('../../package.json');
var assert = require('assert');
Expand All @@ -15,8 +16,10 @@ var Client = module.exports = function(config) {
EventEmitter.call(this);
config = config || {};

this._types = new TypeOverrides(config.types);

this.native = new Native({
types: config.types || require('pg-types')
types: this._types
});

this._queryQueue = [];
Expand Down Expand Up @@ -180,3 +183,11 @@ Client.prototype.cancel = function(query) {
this._queryQueue.splice(this._queryQueue.indexOf(query), 1);
}
};

Client.prototype.setTypeParser = function(oid, format, parseFn) {
return this._types.setTypeParser(oid, format, parseFn);
};

Client.prototype.getTypeParser = function(oid, format) {
return this._types.getTypeParser(oid, format);
};
4 changes: 3 additions & 1 deletion lib/result.js
Expand Up @@ -88,7 +88,7 @@ Result.prototype.addFields = function(fieldDescriptions) {
for(var i = 0; i < fieldDescriptions.length; i++) {
var desc = fieldDescriptions[i];
this.fields.push(desc);
var parser = types.getTypeParser(desc.dataTypeID, desc.format || 'text');
var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text');
this._parsers.push(parser);
//this is some craziness to compile the row result parsing
//results in ~60% speedup on large query result sets
Expand All @@ -99,4 +99,6 @@ Result.prototype.addFields = function(fieldDescriptions) {
}
};

Result.prototype._getTypeParser = types.getTypeParser;

module.exports = Result;
30 changes: 30 additions & 0 deletions lib/type-overrides.js
@@ -0,0 +1,30 @@
var types = require('pg-types');

function TypeOverrides(userTypes) {
this._types = userTypes || types;
this.text = {};
this.binary = {};
}

TypeOverrides.prototype.getOverrides = function(format) {
switch(format) {
case 'text': return this.text;
case 'binary': return this.binary;
default: return {};
}
};

TypeOverrides.prototype.setTypeParser = function(oid, format, parseFn) {
if(typeof format == 'function') {
parseFn = format;
format = 'text';
}
this.getOverrides(format)[oid] = parseFn;
};

TypeOverrides.prototype.getTypeParser = function(oid, format) {
format = format || 'text';
return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format);
};

module.exports = TypeOverrides;
34 changes: 34 additions & 0 deletions test/integration/client/type-parser-override-tests.js
@@ -0,0 +1,34 @@
var helper = require(__dirname + '/test-helper');

function testTypeParser(client, expectedResult, done) {
var boolValue = true;
client.query('CREATE TEMP TABLE parserOverrideTest(id bool)');
client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]);
client.query('SELECT * FROM parserOverrideTest', assert.success(function(result) {
assert.equal(result.rows[0].id, expectedResult);
helper.pg.end();
done();
}));
}

helper.pg.connect(helper.config, assert.success(function(client1, done1) {
helper.pg.connect(helper.config, assert.success(function(client2, done2) {
var boolTypeOID = 16;
client1.setTypeParser(boolTypeOID, function(){
return 'first client';
});
client2.setTypeParser(boolTypeOID, function(){
return 'second client';
});

client1.setTypeParser(boolTypeOID, 'binary', function(){
return 'first client binary';
});
client2.setTypeParser(boolTypeOID, 'binary', function(){
return 'second client binary';
});

testTypeParser(client1, 'first client', done1);
testTypeParser(client2, 'second client', done2);
}));
}));

0 comments on commit d3b47a9

Please sign in to comment.