Node-postgres: Native Bindings override issue

Created on 7 Apr 2016  路  5Comments  路  Source: brianc/node-postgres

The way Native Bindings currently work, is by overriding the library's global settings:

    module.exports.__defineGetter__("native", function () {
        delete module.exports.native;
        module.exports.native = new PG(require('./native'));
        return module.exports.native;
    });

As a result, it creates a conflict when you try using two third-party libraries -

  • one that uses pg via Native Bindings
  • one that uses pg via JavaScript bindings

Just as one library activates Native Bindings, it becomes global, due to Node.js module sharing principle, so it overrides this setting for libraries that do not support Native Bindings.

How to test it

Install pg-native, and declare:

var pg1 = require('pg');
var pg2 = require('pg').native;

Just as pg2 is initialized, any call into pg1 for connect or query goes into the layer for the Native Bindings, thus breaking any module that supports only JavaScript bindings.

Thoughts

I don't know yet how difficult it would be to fix this, or even whether it is possible to make Native Bindings work in parallel with JavaScript Bindings within the same process, without running into conflicts. Any thoughts are welcome!

Most helpful comment

Offf yeah that's just a nasty bug. I'm putting together a PR for it right now. 鉂わ笍

All 5 comments

Below is a complete example showing the issue:

var pg1 = require('pg');
//var pg2 = require('pg').native;

var cn = "pg://postgres@localhost:5000/test"; // invalid connection

pg1.connect(cn, function (err) {
    return console.error(err);
});

it outputs connection error from JavaScript bindings:

{ [Error: connect ECONNREFUSED 127.0.0.1:5000]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 5000 }

Now let's un-comment that second require:

var pg1 = require('pg');
var pg2 = require('pg').native;

var cn = "pg://postgres@localhost:5000/test"; // invalid connection

pg1.connect(cn, function (err) {
    return console.error(err);
});

Now suddenly the error arrives formatted according to the Native Bindings:

error fetching client from pool { [Error: connect ECONNREFUSED 127.0.0.1:5430]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 5430 }

even though we are still using pg1, i.e. the second require overrides global binding settings, so we no longer have access to the JavaScript bindings of the library. This will break any library that tightly relies on JavaScript bindings.

@brianc do you think this is something that is doable?

I would try and do a PR for this, though I'm not sure if it will work. From your perspective, as the insider, is it possible to isolate the two things from each other, and use them in parallel?

Offf yeah that's just a nasty bug. I'm putting together a PR for it right now. 鉂わ笍

@brianc Fantastic!!! Much appreciated!!!

Fixed in version 4.5.3.

My testing confirms that it is working now, at least on the surface - connections are now correct. It would take running the two bindings side-by-side to see if there is any issue remains. Time will tell ;)

@brianc Thank you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

frmoded picture frmoded  路  3Comments

Cosrnos picture Cosrnos  路  3Comments

tonylukasavage picture tonylukasavage  路  4Comments

gajus picture gajus  路  4Comments

gregallenvt picture gregallenvt  路  3Comments