From 6cb167112ef65845dec818e7a888218fbe408483 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Fri, 6 Dec 2013 14:25:46 +1100 Subject: [PATCH 1/9] convert to NAN for Node 0.8->0.11+ support --- binding.gyp | 9 +- package.json | 3 +- src/binding.cc | 217 +++++++----------- .../connection-pool/ending-pool-tests.js | 4 +- 4 files changed, 94 insertions(+), 139 deletions(-) diff --git a/binding.gyp b/binding.gyp index 02c80a4..eae9ef1 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,13 +2,16 @@ 'targets': [ { 'target_name': 'binding', + 'sources': ['src/binding.cc'], + 'include_dirs': [ + ' #include -#include -#include +#include #include #include #include @@ -17,30 +16,11 @@ #define SINGLE_ROW_SUPPORTED #endif -#define THROW(msg) return ThrowException(Exception::Error(String::New(msg))); +#define THROW(msg) NanThrowError(msg); NanReturnUndefined(); using namespace v8; using namespace node; -static Persistent severity_symbol; -static Persistent code_symbol; -static Persistent detail_symbol; -static Persistent hint_symbol; -static Persistent position_symbol; -static Persistent internalPosition_symbol; -static Persistent internalQuery_symbol; -static Persistent where_symbol; -static Persistent file_symbol; -static Persistent line_symbol; -static Persistent routine_symbol; -static Persistent name_symbol; -static Persistent value_symbol; -static Persistent type_symbol; -static Persistent channel_symbol; -static Persistent payload_symbol; -static Persistent emit_symbol; -static Persistent command_symbol; - class Connection : public ObjectWrap { public: @@ -49,30 +29,11 @@ public: static void Init (Handle target) { - HandleScope scope; + NanScope(); Local t = FunctionTemplate::New(New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(String::NewSymbol("Connection")); - - emit_symbol = NODE_PSYMBOL("emit"); - severity_symbol = NODE_PSYMBOL("severity"); - code_symbol = NODE_PSYMBOL("code"); - detail_symbol = NODE_PSYMBOL("detail"); - hint_symbol = NODE_PSYMBOL("hint"); - position_symbol = NODE_PSYMBOL("position"); - internalPosition_symbol = NODE_PSYMBOL("internalPosition"); - internalQuery_symbol = NODE_PSYMBOL("internalQuery"); - where_symbol = NODE_PSYMBOL("where"); - file_symbol = NODE_PSYMBOL("file"); - line_symbol = NODE_PSYMBOL("line"); - routine_symbol = NODE_PSYMBOL("routine"); - name_symbol = NODE_PSYMBOL("name"); - value_symbol = NODE_PSYMBOL("value"); - type_symbol = NODE_PSYMBOL("dataTypeID"); - channel_symbol = NODE_PSYMBOL("channel"); - payload_symbol = NODE_PSYMBOL("payload"); - command_symbol = NODE_PSYMBOL("command"); + t->SetClassName(NanSymbol("Connection")); NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect); #ifdef ESCAPE_SUPPORTED @@ -107,10 +68,9 @@ public: } //v8 entry point into Connection#connect - static Handle - Connect(const Arguments& args) + static NAN_METHOD(Connect) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); if(args.Length() == 0 || !args[0]->IsString()) { THROW("Must include connection string as only argument to connect"); @@ -123,14 +83,13 @@ public: self -> DestroyConnection(); } - return Undefined(); + NanReturnUndefined(); } //v8 entry point into Connection#cancel - static Handle - Cancel(const Arguments& args) + static NAN_METHOD(Cancel) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); bool success = self->Cancel(); @@ -139,15 +98,14 @@ public: self -> DestroyConnection(); } - return Undefined(); + NanReturnUndefined(); } #ifdef ESCAPE_SUPPORTED //v8 entry point into Connection#escapeIdentifier - static Handle - EscapeIdentifier(const Arguments& args) + static NAN_METHOD(EscapeIdentifier) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); char* inputStr = MallocCString(args[0]); @@ -166,14 +124,13 @@ public: Local jsStr = String::New(escapedStr, strlen(escapedStr)); PQfreemem(escapedStr); - return scope.Close(jsStr); + NanReturnValue(jsStr); } //v8 entry point into Connection#escapeLiteral - static Handle - EscapeLiteral(const Arguments& args) + static NAN_METHOD(EscapeLiteral) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); char* inputStr = MallocCString(args[0]); @@ -192,15 +149,14 @@ public: Local jsStr = String::New(escapedStr, strlen(escapedStr)); PQfreemem(escapedStr); - return scope.Close(jsStr); + NanReturnValue(jsStr); } #endif //v8 entry point into Connection#_sendQuery - static Handle - SendQuery(const Arguments& args) + static NAN_METHOD(SendQuery) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); const char *lastErrorMessage; if(!args[0]->IsString()) { @@ -218,23 +174,22 @@ public: } //TODO should we flush before throw? self->Flush(); - return Undefined(); + NanReturnUndefined(); } //v8 entry point into Connection#_sendQueryWithParams - static Handle - SendQueryWithParams(const Arguments& args) + static NAN_METHOD(SendQueryWithParams) { - HandleScope scope; + NanScope(); //dispatch non-prepared parameterized query - return DispatchParameterizedQuery(args, false); + DispatchParameterizedQuery(args, false); + NanReturnUndefined(); } //v8 entry point into Connection#_sendPrepare(string queryName, string queryText, int nParams) - static Handle - SendPrepare(const Arguments& args) + static NAN_METHOD(SendPrepare) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); String::Utf8Value queryName(args[0]); @@ -243,32 +198,33 @@ public: bool singleRowMode = (bool)args[3]->Int32Value(); self->SendPrepare(*queryName, *queryText, length, singleRowMode); - return Undefined(); + NanReturnUndefined(); } //v8 entry point into Connection#_sendQueryPrepared(string queryName, string[] paramValues) - static Handle - SendQueryPrepared(const Arguments& args) + static NAN_METHOD(SendQueryPrepared) { - HandleScope scope; + NanScope(); //dispatch prepared parameterized query - return DispatchParameterizedQuery(args, true); + DispatchParameterizedQuery(args, true); + NanReturnUndefined(); } - static Handle - DispatchParameterizedQuery(const Arguments& args, bool isPrepared) + static void DispatchParameterizedQuery(_NAN_METHOD_ARGS, bool isPrepared) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); String::Utf8Value queryName(args[0]); //TODO this is much copy/pasta code if(!args[0]->IsString()) { - THROW("First parameter must be a string"); + NanThrowError("First parameter must be a string"); + return; } if(!args[1]->IsArray()) { - THROW("Values must be an array"); + NanThrowError("Values must be an array"); + return; } Local jsParams = Local::Cast(args[1]); @@ -277,7 +233,8 @@ public: char** paramValues = ArgToCStringArray(jsParams); if(!paramValues) { - THROW("Unable to allocate char **paramValues from Local of v8 params"); + NanThrowError("Unable to allocate char **paramValues from Local of v8 params"); + return; } char* queryText = MallocCString(args[0]); @@ -293,22 +250,21 @@ public: free(queryText); ReleaseCStringArray(paramValues, len); if(result == 1) { - return Undefined(); + return; } self->EmitLastError(); - THROW("Postgres returned non-1 result from query dispatch."); + NanThrowError("Postgres returned non-1 result from query dispatch."); } //v8 entry point into Connection#end - static Handle - End(const Arguments& args) + static NAN_METHOD(End) { - HandleScope scope; + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); self->End(); - return Undefined(); + NanReturnUndefined(); } uv_poll_t read_watcher_; @@ -340,20 +296,18 @@ public: { } - static Handle - SendCopyFromChunk(const Arguments& args) { - HandleScope scope; + static NAN_METHOD(SendCopyFromChunk) { + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); //TODO handle errors in some way if (args.Length() < 1 && !Buffer::HasInstance(args[0])) { THROW("SendCopyFromChunk requires 1 Buffer argument"); } self->SendCopyFromChunk(args[0]->ToObject()); - return Undefined(); + NanReturnUndefined(); } - static Handle - EndCopyFrom(const Arguments& args) { - HandleScope scope; + static NAN_METHOD(EndCopyFrom) { + NanScope(); Connection *self = ObjectWrap::Unwrap(args.This()); char * error_msg = NULL; if (args[0]->IsString()) { @@ -362,19 +316,18 @@ public: //TODO handle errors in some way self->EndCopyFrom(error_msg); free(error_msg); - return Undefined(); + NanReturnUndefined(); } protected: //v8 entry point to constructor - static Handle - New (const Arguments& args) + static NAN_METHOD(New) { - HandleScope scope; + NanScope(); Connection *connection = new Connection(); connection->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } #ifdef ESCAPE_SUPPORTED @@ -523,7 +476,7 @@ protected: void HandleNotice(const char *message) { - HandleScope scope; + NanScope(); Handle notice = String::New(message); Emit("notice", ¬ice); } @@ -552,7 +505,7 @@ protected: //declare handlescope as this method is entered via a libuv callback //and not part of the public v8 interface - HandleScope scope; + NanScope(); if (this->copyOutMode_) { this->HandleCopyOut(); } @@ -584,8 +537,8 @@ protected: TRACE("PQnotifies"); while ((notify = PQnotifies(connection_))) { Local result = Object::New(); - result->Set(channel_symbol, String::New(notify->relname)); - result->Set(payload_symbol, String::New(notify->extra)); + result->Set(NanSymbol("channel"), String::New(notify->relname)); + result->Set(NanSymbol("payload"), String::New(notify->extra)); Handle res = (Handle)result; Emit("notification", &res); PQfreemem(notify); @@ -604,11 +557,9 @@ protected: bool HandleCopyOut () { char * buffer = NULL; int copied; - Buffer * chunk; copied = PQgetCopyData(connection_, &buffer, 1); while (copied > 0) { - chunk = Buffer::New(buffer, copied); - Local node_chunk = Local::New(chunk->handle_); + Local node_chunk = NanNewBufferHandle(buffer, copied); Emit("copyData", &node_chunk); PQfreemem(buffer); copied = PQgetCopyData(connection_, &buffer, 1); @@ -633,18 +584,18 @@ protected: //javascript & c++ might introduce overhead (requires benchmarking) void EmitRowDescription(const PGresult* result) { - HandleScope scope; + NanScope(); Local row = Array::New(); int fieldCount = PQnfields(result); for(int fieldNumber = 0; fieldNumber < fieldCount; fieldNumber++) { Local field = Object::New(); //name of field char* fieldName = PQfname(result, fieldNumber); - field->Set(name_symbol, String::New(fieldName)); + field->Set(NanSymbol("name"), String::New(fieldName)); //oid of type of field int fieldType = PQftype(result, fieldNumber); - field->Set(type_symbol, Integer::New(fieldType)); + field->Set(NanSymbol("dataTypeID"), Integer::New(fieldType)); row->Set(Integer::New(fieldNumber), field); } @@ -706,10 +657,10 @@ protected: void EmitCommandMetaData(PGresult* result) { - HandleScope scope; + NanScope(); Local info = Object::New(); - info->Set(command_symbol, String::New(PQcmdStatus(result))); - info->Set(value_symbol, String::New(PQcmdTuples(result))); + info->Set(NanSymbol("command"), String::New(PQcmdStatus(result))); + info->Set(NanSymbol("value"), String::New(PQcmdTuples(result))); Handle e = (Handle)info; Emit("_cmdStatus", &e); } @@ -720,7 +671,7 @@ protected: //javascript & c++ might introduce overhead (requires benchmarking) void HandleTuplesResult(const PGresult* result) { - HandleScope scope; + NanScope(); int rowCount = PQntuples(result); for(int rowNumber = 0; rowNumber < rowCount; rowNumber++) { //create result object for this row @@ -744,7 +695,7 @@ protected: void HandleErrorResult(const PGresult* result) { - HandleScope scope; + NanScope(); //instantiate the return object as an Error with the summary Postgres message TRACE("ReadResultField"); const char* errorMessage = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); @@ -756,24 +707,25 @@ protected: Local msg = Local::Cast(Exception::Error(String::New(errorMessage))); TRACE("AttachErrorFields"); //add the other information returned by Postgres to the error object - AttachErrorField(result, msg, severity_symbol, PG_DIAG_SEVERITY); - AttachErrorField(result, msg, code_symbol, PG_DIAG_SQLSTATE); - AttachErrorField(result, msg, detail_symbol, PG_DIAG_MESSAGE_DETAIL); - AttachErrorField(result, msg, hint_symbol, PG_DIAG_MESSAGE_HINT); - AttachErrorField(result, msg, position_symbol, PG_DIAG_STATEMENT_POSITION); - AttachErrorField(result, msg, internalPosition_symbol, PG_DIAG_INTERNAL_POSITION); - AttachErrorField(result, msg, internalQuery_symbol, PG_DIAG_INTERNAL_QUERY); - AttachErrorField(result, msg, where_symbol, PG_DIAG_CONTEXT); - AttachErrorField(result, msg, file_symbol, PG_DIAG_SOURCE_FILE); - AttachErrorField(result, msg, line_symbol, PG_DIAG_SOURCE_LINE); - AttachErrorField(result, msg, routine_symbol, PG_DIAG_SOURCE_FUNCTION); + AttachErrorField(result, msg, NanSymbol("severity"), PG_DIAG_SEVERITY); + AttachErrorField(result, msg, NanSymbol("code"), PG_DIAG_SQLSTATE); + AttachErrorField(result, msg, NanSymbol("detail"), PG_DIAG_MESSAGE_DETAIL); + AttachErrorField(result, msg, NanSymbol("hint"), PG_DIAG_MESSAGE_HINT); + AttachErrorField(result, msg, NanSymbol("position"), PG_DIAG_STATEMENT_POSITION); + AttachErrorField(result, msg, NanSymbol("internalPosition"), PG_DIAG_INTERNAL_POSITION); + AttachErrorField(result, msg, NanSymbol("internalQuery"), PG_DIAG_INTERNAL_QUERY); + AttachErrorField(result, msg, NanSymbol("where"), PG_DIAG_CONTEXT); + AttachErrorField(result, msg, NanSymbol("file"), PG_DIAG_SOURCE_FILE); + AttachErrorField(result, msg, NanSymbol("line"), PG_DIAG_SOURCE_LINE); + AttachErrorField(result, msg, NanSymbol("routine"), PG_DIAG_SOURCE_FUNCTION); Handle m = msg; TRACE("EmitError"); Emit("_error", &m); } - void AttachErrorField(const PGresult *result, const Local msg, const Persistent symbol, int fieldcode) + void AttachErrorField(const PGresult *result, const Local msg, const Local symbol, int fieldcode) { + NanScope(); char *val = PQresultErrorField(result, fieldcode); if(val) { msg->Set(symbol, String::New(val)); @@ -793,26 +745,26 @@ protected: private: //EventEmitter was removed from c++ in node v0.5.x void Emit(const char* message) { - HandleScope scope; + NanScope(); Handle args[1] = { String::New(message) }; Emit(1, args); } void Emit(const char* message, Handle* arg) { - HandleScope scope; + NanScope(); Handle args[2] = { String::New(message), *arg }; Emit(2, args); } void Emit(int length, Handle *args) { - HandleScope scope; + NanScope(); - Local emit_v = this->handle_->Get(emit_symbol); + Local emit_v = NanObjectWrapHandle(this)->Get(NanSymbol("emit")); assert(emit_v->IsFunction()); Local emit_f = emit_v.As(); TryCatch tc; - emit_f->Call(this->handle_, length, args); + emit_f->Call(NanObjectWrapHandle(this), length, args); if(tc.HasCaught()) { FatalException(tc); } @@ -849,6 +801,7 @@ private: void EmitError(const char *message) { + NanScope(); Local exception = Exception::Error(String::New(message)); Emit("_error", &exception); } @@ -994,7 +947,7 @@ private: extern "C" void init (Handle target) { - HandleScope scope; + NanScope(); Connection::Init(target); } NODE_MODULE(binding, init) diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js index da057a5..e227baa 100644 --- a/test/integration/connection-pool/ending-pool-tests.js +++ b/test/integration/connection-pool/ending-pool-tests.js @@ -11,11 +11,11 @@ test('disconnects', function() { helper.pg.connect(config, function(err, client, done) { assert.isNull(err); client.query("SELECT * FROM NOW()", function(err, result) { - process.nextTick(function() { + setTimeout(function() { assert.equal(called, false, "Should not have disconnected yet") sink.add(); done(); - }) + }, 0) }) }) }) From b9c9c6f32965106f0f4fa277aa2ecb8addaa62f9 Mon Sep 17 00:00:00 2001 From: Michael Payne Date: Mon, 9 Dec 2013 23:35:18 -0500 Subject: [PATCH 2/9] Fix for Y10k problem --- lib/types/textParsers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/types/textParsers.js b/lib/types/textParsers.js index 13f8fe1..4d86507 100644 --- a/lib/types/textParsers.js +++ b/lib/types/textParsers.js @@ -3,12 +3,12 @@ var arrayParser = require(__dirname + "/arrayParser.js"); //parses PostgreSQL server formatted date strings into javascript date objects var parseDate = function(isoDate) { //TODO this could do w/ a refactor - var dateMatcher = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d{1,})?/; + var dateMatcher = /(\d{1,})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d{1,})?/; var match = dateMatcher.exec(isoDate); //could not parse date if(!match) { - dateMatcher = /^(\d{4})-(\d{2})-(\d{2})$/; + dateMatcher = /^(\d{1,})-(\d{2})-(\d{2})$/; match = dateMatcher.test(isoDate); if(!match) { return null; From e6a2525540d4d6ce714d17348cdd3f876f76fdb8 Mon Sep 17 00:00:00 2001 From: Michael Payne Date: Mon, 9 Dec 2013 23:35:46 -0500 Subject: [PATCH 3/9] Test for date range extremes --- test/integration/client/type-coercion-tests.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 5c957fc..69d134e 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -151,19 +151,23 @@ test("timestampz round trip", function() { }); if(!helper.config.binary) { - test('early AD & BC date', function() { + test('date range extremes', function() { var client = helper.client(); client.on('error', function(err) { console.log(err); client.end(); }); - client.query('SELECT $1::TIMESTAMPTZ as when', ["0062-03-08 14:32:00"], assert.success(function(res) { - assert.equal(res.rows[0].when.getFullYear(), 62); + // PostgreSQL supports date range of 4713 BCE to 294276 CE + // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html + // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE + // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 + client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function(res) { + assert.equal(res.rows[0].when.getFullYear(), 275760); })) - client.query('SELECT $1::TIMESTAMPTZ as when', ["0062-03-08 14:32:00 BC"], assert.success(function(res) { - assert.equal(res.rows[0].when.getFullYear(), -62); + client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function(res) { + assert.equal(res.rows[0].when.getFullYear(), -4713); })) client.on('drain', client.end.bind(client)); From 6d4a70702ef6d00004a89687ab402f576418b233 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 12 Dec 2013 18:28:29 -0600 Subject: [PATCH 4/9] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 03375e1..65eeaf6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "2.8.3", + "version": "2.8.4", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 2a523c8f331cea9799c7f24f3d2c70b43cb3d339 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Thu, 19 Dec 2013 10:24:05 +1100 Subject: [PATCH 5/9] fix quoting for Windows compile --- binding.gyp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding.gyp b/binding.gyp index eae9ef1..bdc9dfd 100644 --- a/binding.gyp +++ b/binding.gyp @@ -5,7 +5,7 @@ 'sources': ['src/binding.cc'], 'include_dirs': [ ' Date: Thu, 19 Dec 2013 15:37:26 -0300 Subject: [PATCH 6/9] Set database on socket string connection Allows to conect to a specific database trough this ways: pg.connect('/some/path database', callback); pg.connect('socket:/some/path?db=database', callback) pg.connect('socket:/some/path?db=database&encoding=utf8', callback) --- lib/connection-parameters.js | 16 ++++++--- .../connection-parameters/creation-tests.js | 34 +++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index f21da1f..e69fc5b 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -12,16 +12,24 @@ var val = function(key, config) { var url = require('url'); //parses a connection string var parse = function(str) { + var config; //unix socket if(str.charAt(0) === '/') { - return { host: str }; + config = str.split(' '); + return { host: config[0], database: config[1] }; } // url parse expects spaces encoded as %20 - str = encodeURI(str); + if(/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) str = encodeURI(str); var result = url.parse(str, true); - var config = {}; + config = {}; + if(result.protocol == 'socket:') { + config.host = decodeURI(result.pathname); + config.database = result.query.db; + config.client_encoding = result.query.encoding; + return config; + } config.host = result.hostname; - config.database = result.pathname ? result.pathname.slice(1) : null; + config.database = result.pathname ? decodeURI(result.pathname.slice(1)) : null; var auth = (result.auth || ':').split(':'); config.user = auth[0]; config.password = auth[1]; diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 0624c79..aaab121 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -47,10 +47,44 @@ test('ConnectionParameters initializing from config', function() { assert.ok(subject.isDomainSocket === false); }); +test('escape spaces if present', function() { + subject = new ConnectionParameters('postgres://localhost/post gres'); + assert.equal(subject.database, 'post gres'); +}); + +test('do not double escape spaces', function() { + subject = new ConnectionParameters('postgres://localhost/post%20gres'); + assert.equal(subject.database, 'post gres'); +}); + test('initializing with unix domain socket', function() { var subject = new ConnectionParameters('/var/run/'); assert.ok(subject.isDomainSocket); assert.equal(subject.host, '/var/run/'); + assert.equal(subject.database, defaults.user); +}); + +test('initializing with unix domain socket and a specific database, the simple way', function() { + var subject = new ConnectionParameters('/var/run/ mydb'); + assert.ok(subject.isDomainSocket); + assert.equal(subject.host, '/var/run/'); + assert.equal(subject.database, 'mydb'); +}); + +test('initializing with unix domain socket, the health way', function() { + var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8'); + assert.ok(subject.isDomainSocket); + assert.equal(subject.host, '/some path/'); + assert.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); + assert.equal(subject.client_encoding, 'utf8'); +}); + +test('initializing with unix domain socket, the escaped health way', function() { + var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); + assert.ok(subject.isDomainSocket); + assert.equal(subject.host, '/some path/'); + assert.equal(subject.database, 'my+db'); + assert.equal(subject.client_encoding, 'utf8'); }); test('libpq connection string building', function() { From 1884feb14507335674483eec809428868e49a405 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2013 22:23:53 -0600 Subject: [PATCH 7/9] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 65eeaf6..ff41445 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "2.8.4", + "version": "2.8.5", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From edcc39b53fc5c3722bf448ddda1fab323d359c8d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2013 22:34:49 -0600 Subject: [PATCH 8/9] Update news --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index bddf7fa..c98f369 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,9 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### v2.9.0 +- Add better support for [unix domain socket](https://github.com/brianc/node-postgres/pull/487) connections + ### v2.8.0 - Add support for parsing JSON[] and UUID[] result types From 30fc4c2a2c213018c637fd077de27fb42e83db74 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2013 22:34:54 -0600 Subject: [PATCH 9/9] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff41445..eb69d96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "2.8.5", + "version": "2.9.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres",