You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

7 lines
18 KiB

{
"version": 3,
"sources": ["../../../src/dialects/postgres/connection-manager.js"],
"sourcesContent": ["'use strict';\n\nconst _ = require('lodash');\nconst AbstractConnectionManager = require('../abstract/connection-manager');\nconst { logger } = require('../../utils/logger');\nconst debug = logger.debugContext('connection:pg');\nconst sequelizeErrors = require('../../errors');\nconst semver = require('semver');\nconst dataTypes = require('../../data-types');\nconst momentTz = require('moment-timezone');\nconst { promisify } = require('util');\n\nclass ConnectionManager extends AbstractConnectionManager {\n constructor(dialect, sequelize) {\n sequelize.config.port = sequelize.config.port || 5432;\n super(dialect, sequelize);\n\n const pgLib = this._loadDialectModule('pg');\n this.lib = this.sequelize.config.native ? pgLib.native : pgLib;\n\n this._clearDynamicOIDs();\n this._clearTypeParser();\n this.refreshTypeParser(dataTypes.postgres);\n }\n\n // Expose this as a method so that the parsing may be updated when the user has added additional, custom types\n _refreshTypeParser(dataType) {\n const arrayParserBuilder = parser => {\n return value => this.lib.types.arrayParser.create(value, parser).parse();\n };\n const rangeParserBuilder = parser => {\n return value => dataType.parse(value, { parser });\n };\n\n // Set range parsers\n if (dataType.key.toLowerCase() === 'range') {\n for (const name in this.nameOidMap) {\n const entry = this.nameOidMap[name];\n if (! entry.rangeOid) continue;\n\n const rangeParser = rangeParserBuilder(this.getTypeParser(entry.oid));\n const arrayRangeParser = arrayParserBuilder(rangeParser);\n\n this.oidParserMap.set(entry.rangeOid, rangeParser);\n if (! entry.arrayRangeOid) continue;\n this.oidParserMap.set(entry.arrayRangeOid, arrayRangeParser);\n }\n return;\n }\n\n // Create parsers for normal or enum data types\n const parser = value => dataType.parse(value);\n const arrayParser = arrayParserBuilder(parser);\n\n // Set enum parsers\n if (dataType.key.toLowerCase() === 'enum') {\n this.enumOids.oids.forEach(oid => {\n this.oidParserMap.set(oid, parser);\n });\n this.enumOids.arrayOids.forEach(arrayOid => {\n this.oidParserMap.set(arrayOid, arrayParser);\n });\n return;\n }\n\n // Set parsers for normal data types\n dataType.types.postgres.forEach(name => {\n if (! this.nameOidMap[name]) return;\n this.oidParserMap.set(this.nameOidMap[name].oid, parser);\n\n if (! this.nameOidMap[name].arrayOid) return;\n this.oidParserMap.set(this.nameOidMap[name].arrayOid, arrayParser);\n });\n }\n\n _clearTypeParser() {\n this.oidParserMap = new Map();\n }\n\n getTypeParser(oid, ...args) {\n if (this.oidParserMap.get(oid)) return this.oidParserMap.get(oid);\n\n return this.lib.types.getTypeParser(oid, ...args);\n }\n\n async connect(config) {\n config.user = config.username;\n const connectionConfig = _.pick(config, [\n 'user', 'password', 'host', 'database', 'port'\n ]);\n\n connectionConfig.types = {\n getTypeParser: ConnectionManager.prototype.getTypeParser.bind(this)\n };\n\n if (config.dialectOptions) {\n _.merge(connectionConfig,\n _.pick(config.dialectOptions, [\n // see [http://www.postgresql.org/docs/9.3/static/runtime-config-logging.html#GUC-APPLICATION-NAME]\n 'application_name',\n // choose the SSL mode with the PGSSLMODE environment variable\n // object format: [https://github.com/brianc/node-postgres/blob/ee19e74ffa6309c9c5e8e01746261a8f651661f8/lib/connection.js#L79]\n // see also [http://www.postgresql.org/docs/9.3/static/libpq-ssl.html]\n 'ssl',\n // In addition to the values accepted by the corresponding server,\n // you can use \"auto\" to determine the right encoding from the\n // current locale in the client (LC_CTYPE environment variable on Unix systems)\n 'client_encoding',\n // !! DO NOT SET THIS TO TRUE !!\n // (unless you know what you're doing)\n // see [http://www.postgresql.org/message-id/flat/bc9549a50706040852u27633f41ib1e6b09f8339d845@mail.gmail.com#bc9549a50706040852u27633f41ib1e6b09f8339d845@mail.gmail.com]\n 'binary',\n // This should help with backends incorrectly considering idle clients to be dead and prematurely disconnecting them.\n // this feature has been added in pg module v6.0.0, check pg/CHANGELOG.md\n 'keepAlive',\n // Times out queries after a set time in milliseconds in the database end. Added in pg v7.3\n 'statement_timeout',\n // Times out queries after a set time in milliseconds in client end, query would be still running in database end.\n 'query_timeout',\n // Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds. Added in pg v7.17.0 only supported in postgres >= 10\n 'idle_in_transaction_session_timeout',\n // Postgres allows additional session variables to be configured in the connection string in the `options` param.\n // see [https://www.postgresql.org/docs/14/libpq-connect.html#LIBPQ-CONNECT-OPTIONS]\n 'options'\n ]));\n }\n\n const connection = await new Promise((resolve, reject) => {\n let responded = false;\n\n const connection = new this.lib.Client(connectionConfig);\n\n const parameterHandler = message => {\n switch (message.parameterName) {\n case 'server_version':\n if (this.sequelize.options.databaseVersion === 0) {\n const version = semver.coerce(message.parameterValue).version;\n this.sequelize.options.databaseVersion = semver.valid(version)\n ? version\n : this.dialect.defaultVersion;\n }\n break;\n case 'standard_conforming_strings':\n connection['standard_conforming_strings'] = message.parameterValue;\n break;\n }\n };\n\n const endHandler = () => {\n debug('connection timeout');\n if (!responded) {\n reject(new sequelizeErrors.ConnectionTimedOutError(new Error('Connection timed out')));\n }\n };\n\n // If we didn't ever hear from the client.connect() callback the connection timeout\n // node-postgres does not treat this as an error since no active query was ever emitted\n connection.once('end', endHandler);\n\n if (!this.sequelize.config.native) {\n // Receive various server parameters for further configuration\n connection.connection.on('parameterStatus', parameterHandler);\n }\n\n connection.connect(err => {\n responded = true;\n\n if (!this.sequelize.config.native) {\n // remove parameter handler\n connection.connection.removeListener('parameterStatus', parameterHandler);\n }\n\n if (err) {\n if (err.code) {\n switch (err.code) {\n case 'ECONNREFUSED':\n reject(new sequelizeErrors.ConnectionRefusedError(err));\n break;\n case 'ENOTFOUND':\n reject(new sequelizeErrors.HostNotFoundError(err));\n break;\n case 'EHOSTUNREACH':\n reject(new sequelizeErrors.HostNotReachableError(err));\n break;\n case 'EINVAL':\n reject(new sequelizeErrors.InvalidConnectionError(err));\n break;\n default:\n reject(new sequelizeErrors.ConnectionError(err));\n break;\n }\n } else {\n reject(new sequelizeErrors.ConnectionError(err));\n }\n } else {\n debug('connection acquired');\n connection.removeListener('end', endHandler);\n resolve(connection);\n }\n });\n });\n\n // Don't let a Postgres restart (or error) to take down the whole app\n connection.once('error', error => {\n connection._invalid = true;\n debug(`connection error ${error.code || error.message}`);\n this.pool.destroy(connection);\n });\n\n let query = '';\n\n if (this.sequelize.options.standardConformingStrings !== false && connection['standard_conforming_strings'] !== 'on') {\n // Disable escape characters in strings\n // see https://github.com/sequelize/sequelize/issues/3545 (security issue)\n // see https://www.postgresql.org/docs/current/static/runtime-config-compatible.html#GUC-STANDARD-CONFORMING-STRINGS\n query += 'SET standard_conforming_strings=on;';\n }\n\n if (this.sequelize.options.clientMinMessages !== undefined) {\n console.warn('Usage of \"options.clientMinMessages\" is deprecated and will be removed in v7.');\n console.warn('Please use the sequelize option \"dialectOptions.clientMinMessages\" instead.');\n }\n\n // Redshift dosen't support client_min_messages, use 'ignore' to skip this settings.\n // If no option, the default value in sequelize is 'warning'\n if ( !( config.dialectOptions && config.dialectOptions.clientMinMessages && config.dialectOptions.clientMinMessages.toLowerCase() === 'ignore' ||\n this.sequelize.options.clientMinMessages === false ) ) {\n const clientMinMessages = config.dialectOptions && config.dialectOptions.clientMinMessages || this.sequelize.options.clientMinMessages || 'warning';\n query += `SET client_min_messages TO ${clientMinMessages};`;\n\n }\n\n if (!this.sequelize.config.keepDefaultTimezone) {\n const isZone = !!momentTz.tz.zone(this.sequelize.options.timezone);\n if (isZone) {\n query += `SET TIME ZONE '${this.sequelize.options.timezone}';`;\n } else {\n query += `SET TIME ZONE INTERVAL '${this.sequelize.options.timezone}' HOUR TO MINUTE;`;\n }\n }\n\n if (query) {\n await connection.query(query);\n }\n if (Object.keys(this.nameOidMap).length === 0 &&\n this.enumOids.oids.length === 0 &&\n this.enumOids.arrayOids.length === 0) {\n await this._refreshDynamicOIDs(connection);\n }\n\n return connection;\n }\n\n async disconnect(connection) {\n if (connection._ending) {\n debug('connection tried to disconnect but was already at ENDING state');\n return;\n }\n\n return await promisify(callback => connection.end(callback))();\n }\n\n validate(connection) {\n return !connection._invalid && !connection._ending;\n }\n\n async _refreshDynamicOIDs(connection) {\n const databaseVersion = this.sequelize.options.databaseVersion;\n const supportedVersion = '8.3.0';\n\n // Check for supported version\n if ( (databaseVersion && semver.gte(databaseVersion, supportedVersion)) === false) {\n return;\n }\n\n const results = await (connection || this.sequelize).query(\n 'WITH ranges AS (' +\n ' SELECT pg_range.rngtypid, pg_type.typname AS rngtypname,' +\n ' pg_type.typarray AS rngtyparray, pg_range.rngsubtype' +\n ' FROM pg_range LEFT OUTER JOIN pg_type ON pg_type.oid = pg_range.rngtypid' +\n ')' +\n 'SELECT pg_type.typname, pg_type.typtype, pg_type.oid, pg_type.typarray,' +\n ' ranges.rngtypname, ranges.rngtypid, ranges.rngtyparray' +\n ' FROM pg_type LEFT OUTER JOIN ranges ON pg_type.oid = ranges.rngsubtype' +\n ' WHERE (pg_type.typtype IN(\\'b\\', \\'e\\'));'\n );\n\n let result = Array.isArray(results) ? results.pop() : results;\n\n // When searchPath is prepended then two statements are executed and the result is\n // an array of those two statements. First one is the SET search_path and second is\n // the SELECT query result.\n if (Array.isArray(result)) {\n if (result[0].command === 'SET') {\n result = result.pop();\n }\n }\n\n const newNameOidMap = {};\n const newEnumOids = { oids: [], arrayOids: [] };\n\n for (const row of result.rows) {\n // Mapping enums, handled separatedly\n if (row.typtype === 'e') {\n newEnumOids.oids.push(row.oid);\n if (row.typarray) newEnumOids.arrayOids.push(row.typarray);\n continue;\n }\n\n // Mapping base types and their arrays\n newNameOidMap[row.typname] = { oid: row.oid };\n if (row.typarray) newNameOidMap[row.typname].arrayOid = row.typarray;\n\n // Mapping ranges(of base types) and their arrays\n if (row.rngtypid) {\n newNameOidMap[row.typname].rangeOid = row.rngtypid;\n if (row.rngtyparray) newNameOidMap[row.typname].arrayRangeOid = row.rngtyparray;\n }\n }\n\n // Replace all OID mappings. Avoids temporary empty OID mappings.\n this.nameOidMap = newNameOidMap;\n this.enumOids = newEnumOids;\n\n this.refreshTypeParser(dataTypes.postgres);\n }\n\n _clearDynamicOIDs() {\n this.nameOidMap = {};\n this.enumOids = { oids: [], arrayOids: [] };\n }\n}\n\nmodule.exports = ConnectionManager;\nmodule.exports.ConnectionManager = ConnectionManager;\nmodule.exports.default = ConnectionManager;\n"],
"mappings": "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",
"names": []
}