Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/pg/lib/connection-parameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const defaults = require('./defaults')
const parse = require('pg-connection-string').parse // parses a connection string

const val = function (key, config, envVar) {
if (config[key]) {
return config[key]
}

if (envVar === undefined) {
envVar = process.env['PG' + key.toUpperCase()]
} else if (envVar === false) {
Expand All @@ -15,7 +19,7 @@ const val = function (key, config, envVar) {
envVar = process.env[envVar]
}

return config[key] || envVar || defaults[key]
return envVar || defaults[key]
}

const readSSLConfigFromEnvironment = function () {
Expand Down
9 changes: 8 additions & 1 deletion packages/pg/lib/defaults.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
'use strict'

let user
try {
user = process.platform === 'win32' ? process.env.USERNAME : process.env.USER
} catch {
// ignore, e.g., Deno without --allow-env
}

module.exports = {
// database host. defaults to localhost
host: 'localhost',

// database user's name
user: process.platform === 'win32' ? process.env.USERNAME : process.env.USER,
user,

// name of database to connect
database: undefined,
Expand Down
57 changes: 33 additions & 24 deletions packages/pg/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,40 @@ const PG = function (clientConstructor) {
this.utils = utils
}

if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') {
module.exports = new PG(require('./native'))
} else {
module.exports = new PG(Client)
let clientConstructor = Client

// lazy require native module...the native module may not have installed
Object.defineProperty(module.exports, 'native', {
configurable: true,
enumerable: false,
get() {
let native = null
try {
native = new PG(require('./native'))
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') {
throw err
}
let forceNative = false
try {
forceNative = !!process.env.NODE_PG_FORCE_NATIVE
} catch {
// ignore, e.g., Deno without --allow-env
}

if (forceNative) {
Copy link

@NickCrews NickCrews Oct 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am reading this right, if you are in a deno environment with no --allow-env, then the above will always error, and forceNative will always remain in its default of false, and so it will be impossible to use the native driver. I'm not sure how much of a dealbreaker this actually is (eg does the native driver actually run in deno???).

Copy link
Collaborator

@charmander charmander Oct 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the environment variable was always a mistake (same with the property), and breaking it in a way that’s backwards-compatible is fine. If a future API of the pg package even includes pg-native at all, I suggest it should be imported from pg/native and that there should be only the one way to do it. (I also recommend never using pg-native, since it has extra bugs and less maintenance. The inherent performance difference is minimal, though both pg and pg-native are both missing key optimizations right now.)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I also agree that the best API would be to import from pg/native. Then we can skip any new APIs here to select the backend. How about this then?

const PG = ... // same as before

function makeClient(config) {
    let useNative = false;
    try {
        useNative = typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined'
    } catch {
        // ignore, eg in Deno sandbox without --allow-env
    }
    const actualClient = useNative ? require('./native') : Client
    return actualClient(config)
}

module.exports = new PG(makeClient)

// lazy require native module...the native module may not have installed
  Object.defineProperty(module.exports, 'native', {
...

Is there anything else you need to merge this PR? With that change I'm happy. Honestly, the current suggested implementation is similar enough, I would be fine merging that as well.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the environment variable was always a mistake (same with the property), and breaking it in a way that’s backwards-compatible is fine. If a future API of the pg package even includes pg-native at all, I suggest it should be imported from pg/native and that there should be only the one way to do it. (I also recommend never using pg-native, since it has extra bugs and less maintenance. The inherent performance difference is minimal, though both pg and pg-native are both missing key optimizations right now.)

I agree with all of this so hard. There are some legacy things in node-postgres from a long time ago when I was a lot less experienced, and this is one of them. This is one of the things that will definitely die with [email protected]

clientConstructor = require('./native')
}

module.exports = new PG(clientConstructor)

// lazy require native module...the native module may not have installed
Object.defineProperty(module.exports, 'native', {
configurable: true,
enumerable: false,
get() {
let native = null
try {
native = new PG(require('./native'))
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') {
throw err
}
}

// overwrite module.exports.native so that getter is never called again
Object.defineProperty(module.exports, 'native', {
value: native,
})
// overwrite module.exports.native so that getter is never called again
Object.defineProperty(module.exports, 'native', {
value: native,
})

return native
},
})
}
return native
},
})