diff --git a/lib/client.js b/lib/client.js index 4e3f8112..563606f5 100644 --- a/lib/client.js +++ b/lib/client.js @@ -10,7 +10,7 @@ var Connection = require(__dirname + '/connection'); var Client = function(config) { EventEmitter.call(this); if(typeof config === 'string') { - config = utils.parseConnectionString(config) + config = utils.normalizeConnectionInfo(config) } config = config || {}; this.user = config.user || defaults.user; @@ -31,7 +31,12 @@ var p = Client.prototype; p.connect = function() { var self = this; var con = this.connection; - con.connect(this.port, this.host); + if(this.host && this.host.indexOf('/') === 0) { + con.connect(this.host + '/.s.PGSQL.' + this.port); + } else { + con.connect(this.port, this.host); + } + //once connection is established send startup message con.on('connect', function() { diff --git a/lib/defaults.js b/lib/defaults.js index 3bd8e794..52b30896 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,10 +1,10 @@ module.exports = { //database user's name - user: '', + user: process.env.USER, //name of database to connect - database: '', + database: process.env.USER, //database user's password - password: '', + password: null, //database port port: 5432, //number of rows to return at a time from a prepared statement's diff --git a/lib/index.js b/lib/index.js index 21ed6d2e..20cfc47d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,4 @@ var EventEmitter = require('events').EventEmitter; - var Client = require(__dirname+'/client'); var defaults = require(__dirname + '/defaults'); var pool = require(__dirname + "/client-pool").init(Client); diff --git a/lib/utils.js b/lib/utils.js index 3b147ac2..3813ec94 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,5 @@ var url = require('url'); +var defaults = require(__dirname + "/defaults"); var events = require('events'); var sys = require('sys'); @@ -74,17 +75,49 @@ p._pulse = function(item, cb) { return true; } return false; -} +}; + +var parseConnectionString = function(str) { + //unix socket + if(str.charAt(0) === '/') { + return { host: str }; + } + var result = url.parse(str); + var config = {}; + config.host = result.hostname; + config.database = result.pathname ? result.pathname.slice(1) : null + var auth = (result.auth || ':').split(':'); + config.user = auth[0]; + config.password = auth[1]; + config.port = result.port; + return config; +}; + +//allows passing false as property to remove it from config +var norm = function(config, propName) { + config[propName] = (config[propName] || (config[propName] === false ? undefined : defaults[propName])) +}; + +//normalizes connection info +//which can be in the form of an object +//or a connection string +var normalizeConnectionInfo = function(config) { + switch(typeof config) { + case 'object': + norm(config, 'user'); + norm(config, 'password'); + norm(config, 'host'); + norm(config, 'port'); + norm(config, 'database'); + return config; + case 'string': + return normalizeConnectionInfo(parseConnectionString(config)); + default: + throw new Error("Unrecognized connection config parameter: " + config); + } +}; module.exports = { Pool: Pool, - parseConnectionString: function(str) { - var result = url.parse(str); - result.host = result.hostname; - result.database = result.pathname ? result.pathname.slice(1) : null - var auth = (result.auth || ':').split(':'); - result.user = auth[0]; - result.password = auth[1]; - return result; - } + normalizeConnectionInfo: normalizeConnectionInfo } diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index d380f73b..4b2e243c 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -3,9 +3,9 @@ var pg = require("index"); test('default values', function() { assert.same(pg.defaults,{ - user: '', - database: '', - password: '', + user: process.env.USER, + database: process.env.USER, + password: null, port: 5432, rows: 0, poolSize: 10 @@ -13,9 +13,9 @@ test('default values', function() { test('are used in new clients', function() { var client = new pg.Client(); assert.same(client,{ - user: '', - database: '', - password: '', + user: process.env.USER, + database: process.env.USER, + password: null, port: 5432 }) }) diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 4db39d8f..475acf79 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -7,3 +7,11 @@ test("empty query message handling", function() { }); client.query(""); }); + +test('callback supported', assert.calls(function() { + client.query("", function(err, result) { + assert.isNull(err); + assert.empty(result.rows); + }) +})) + diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index b6ab690d..ff2fac0d 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -32,20 +32,11 @@ test("named prepared statement", function() { name: queryName }); - test("is parsed", function() { - client.connection.on('parseComplete', function() { - parseCount++; - }); - }); - assert.emits(query, 'row', function(row) { assert.equal(row.name, 'Brian'); }); assert.emits(query, 'end', function() { - test("query was parsed", function() { - assert.equal(parseCount, 1); - }); }); }); @@ -61,9 +52,6 @@ test("named prepared statement", function() { }); assert.emits(cachedQuery, 'end', function() { - test("query was only parsed one time", function() { - assert.equal(parseCount, 1, "Should not have reparsed query"); - }); }); }); @@ -87,7 +75,7 @@ test("named prepared statement", function() { }); assert.emits(q, 'end', function() { - assert.equal(parseCount, 1); + }); }); }); diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index 4a908114..cb60119b 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -4,8 +4,8 @@ test('client settings', function() { test('defaults', function() { var client = new Client(); - assert.equal(client.user, ''); - assert.equal(client.database, ''); + assert.equal(client.user, process.env.USER); + assert.equal(client.database, process.env.USER); assert.equal(client.port, 5432); }); @@ -41,12 +41,26 @@ test('initializing from a config string', function() { test('when not including all values the defaults are used', function() { var client = new Client("pg://host1") - assert.equal(client.user, "") - assert.equal(client.password, "") + assert.equal(client.user, process.env.USER) + assert.equal(client.password, null) assert.equal(client.host, "host1") assert.equal(client.port, 5432) - assert.equal(client.database, "") + assert.equal(client.database, process.env.USER) }) }) + +test('calls connect correctly on connection', function() { + var client = new Client("/tmp"); + var usedPort = ""; + var usedHost = ""; + client.connection.connect = function(port, host) { + usedPort = port; + usedHost = host; + }; + client.connect(); + assert.equal(usedPort, "/tmp/.s.PGSQL.5432"); + assert.strictEqual(usedHost, undefined) +}) + diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 1fa733c9..428ef406 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -1,5 +1,7 @@ require(__dirname + '/test-helper'); -var Pool = require(__dirname + "/../../lib/utils").Pool; +var utils = require(__dirname + "/../../lib/utils"); +var Pool = utils.Pool; +var defaults = require(__dirname + "/../../lib").defaults; //this tests the monkey patching //to ensure comptability with older @@ -109,8 +111,75 @@ test('when creating async new pool members', function() { })) })) }) - }) +test('normalizing connection info', function() { + test('with objects', function() { + test('empty object uses defaults', function() { + var input = {}; + var output = utils.normalizeConnectionInfo(input); + assert.equal(output.user, defaults.user); + assert.equal(output.database, defaults.database); + assert.equal(output.port, defaults.port); + assert.equal(output.host, defaults.host); + assert.equal(output.password, defaults.password); + }); + test('full object ignores defaults', function() { + var input = { + user: 'test1', + database: 'test2', + port: 'test3', + host: 'test4', + password: 'test5' + }; + assert.equal(utils.normalizeConnectionInfo(input), input); + }); + test('connection string', function() { + test('non-unix socket', function() { + test('uses defaults', function() { + var input = ""; + var output = utils.normalizeConnectionInfo(input); + assert.equal(output.user, defaults.user); + assert.equal(output.database, defaults.database); + assert.equal(output.port, defaults.port); + assert.equal(output.host, defaults.host); + assert.equal(output.password, defaults.password); + }); + test('ignores defaults if string contains them all', function() { + var input = "tcp://user1:pass2@host3:3333/databaseName"; + var output = utils.normalizeConnectionInfo(input); + assert.equal(output.user, 'user1'); + assert.equal(output.database, 'databaseName'); + assert.equal(output.port, 3333); + assert.equal(output.host, 'host3'); + assert.equal(output.password, 'pass2'); + }) + }); + + test('unix socket', function() { + test('uses defaults', function() { + var input = "/var/run/postgresql"; + var output = utils.normalizeConnectionInfo(input); + assert.equal(output.user, process.env.USER); + assert.equal(output.host, '/var/run/postgresql'); + assert.equal(output.database, process.env.USER); + assert.equal(output.port, 5432); + }); + + test('uses overridden defaults', function() { + defaults.host = "/var/run/postgresql"; + defaults.user = "boom"; + defaults.password = "yeah"; + defaults.port = 1234; + var output = utils.normalizeConnectionInfo("asdf"); + assert.equal(output.user, "boom"); + assert.equal(output.password, "yeah"); + assert.equal(output.port, 1234); + assert.equal(output.host, "/var/run/postgresql"); + }) + }) + }) + }) +})