不要怂,就是干,撸起袖子干!

Commit 4383922a by Ali Taheri Moghaddar Committed by Felix Becker

feat(dependency): Support pg version 7 (#7888)

1 parent 85ee83d9
...@@ -201,7 +201,7 @@ const sequelize = new Sequelize('sqlite:relativePath/dbname.db') ...@@ -201,7 +201,7 @@ const sequelize = new Sequelize('sqlite:relativePath/dbname.db')
### PostgreSQL ### PostgreSQL
The library for PostgreSQL is`pg@~3.6.0` You'll just need to define the dialect: The library for PostgreSQL is`pg@^5.0.0 || ^6.0.0 || ^7.0.0` You'll just need to define the dialect:
```js ```js
const sequelize = new Sequelize('database', 'username', 'password', { const sequelize = new Sequelize('database', 'username', 'password', {
......
...@@ -153,10 +153,8 @@ class ConnectionManager extends AbstractConnectionManager { ...@@ -153,10 +153,8 @@ class ConnectionManager extends AbstractConnectionManager {
query += 'SELECT typname, oid, typarray FROM pg_type WHERE typtype = \'b\' AND typname IN (\'hstore\', \'geometry\', \'geography\')'; query += 'SELECT typname, oid, typarray FROM pg_type WHERE typtype = \'b\' AND typname IN (\'hstore\', \'geometry\', \'geography\')';
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => connection.query(query, (error, result) => error ? reject(error) : resolve(result))).then(result => {
connection.query(query) for (const row of result.rows) {
.on('error', err => reject(err))
.on('row', row => {
let type; let type;
if (row.typname === 'geometry') { if (row.typname === 'geometry') {
type = dataTypes.postgres.GEOMETRY; type = dataTypes.postgres.GEOMETRY;
...@@ -170,8 +168,7 @@ class ConnectionManager extends AbstractConnectionManager { ...@@ -170,8 +168,7 @@ class ConnectionManager extends AbstractConnectionManager {
type.types.postgres.array_oids.push(row.typarray); type.types.postgres.array_oids.push(row.typarray);
this._refreshTypeParser(type); this._refreshTypeParser(type);
}) }
.on('end', () => resolve());
}); });
}); });
} }
......
...@@ -60,9 +60,9 @@ class Query extends AbstractQuery { ...@@ -60,9 +60,9 @@ class Query extends AbstractQuery {
this.sql = this.sequelize.queryInterface.QueryGenerator.setSearchPath(this.options.searchPath) + sql; this.sql = this.sequelize.queryInterface.QueryGenerator.setSearchPath(this.options.searchPath) + sql;
} }
const query = parameters && parameters.length ? this.client.query(this.sql, parameters) : this.client.query(this.sql); const query = parameters && parameters.length
const rows = []; ? new Promise((resolve, reject) => this.client.query(this.sql, parameters, (error, result) => error ? reject(error) : resolve(result)))
let receivedError = false; : new Promise((resolve, reject) => this.client.query(this.sql, (error, result) => error ? reject(error) : resolve(result)));
//do we need benchmark for this query execution //do we need benchmark for this query execution
const benchmark = this.sequelize.options.benchmark || this.options.benchmark; const benchmark = this.sequelize.options.benchmark || this.options.benchmark;
...@@ -76,39 +76,27 @@ class Query extends AbstractQuery { ...@@ -76,39 +76,27 @@ class Query extends AbstractQuery {
debug(`executing(${this.client.uuid || 'default'}) : ${this.sql}`); debug(`executing(${this.client.uuid || 'default'}) : ${this.sql}`);
return new Promise((resolve, reject) => { return query.catch(err => {
query.on('row', row => {
rows.push(row);
});
query.on('error', err => {
// set the client so that it will be reaped if the connection resets while executing // set the client so that it will be reaped if the connection resets while executing
if (err.code === 'ECONNRESET') { if (err.code === 'ECONNRESET') {
this.client._invalid = true; this.client._invalid = true;
} }
receivedError = true;
err.sql = sql; err.sql = sql;
reject(this.formatError(err)); throw this.formatError(err);
}); })
.then(queryResult => {
query.on('end', result => {
debug(`executed(${this.client.uuid || 'default'}) : ${this.sql}`); debug(`executed(${this.client.uuid || 'default'}) : ${this.sql}`);
if (benchmark) { if (benchmark) {
this.sequelize.log('Executed (' + (this.client.uuid || 'default') + '): ' + this.sql, Date.now() - queryBegin, this.options); this.sequelize.log('Executed (' + (this.client.uuid || 'default') + '): ' + this.sql, Date.now() - queryBegin, this.options);
} }
if (receivedError) { return queryResult;
return; })
} .then(queryResult => {
const rows = queryResult.rows;
resolve([rows, sql, result]); const rowCount = queryResult.rowCount;
});
}).spread((rows, sql, result) => {
const results = rows;
const isTableNameQuery = sql.indexOf('SELECT table_name FROM information_schema.tables') === 0; const isTableNameQuery = sql.indexOf('SELECT table_name FROM information_schema.tables') === 0;
const isRelNameQuery = sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0; const isRelNameQuery = sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0;
...@@ -128,30 +116,29 @@ class Query extends AbstractQuery { ...@@ -128,30 +116,29 @@ class Query extends AbstractQuery {
detail: rows[0].sequelize_caught_exception detail: rows[0].sequelize_caught_exception
}); });
} else { } else {
rows = rows.map(row => { for (const row of rows) {
delete row.sequelize_caught_exception; delete row.sequelize_caught_exception;
return row; }
});
} }
} }
if (this.isShowIndexesQuery()) { if (this.isShowIndexesQuery()) {
for (const result of results) { for (const row of rows) {
const attributes = /ON .*? (?:USING .*?\s)?\(([^]*)\)/gi.exec(result.definition)[1].split(','); const attributes = /ON .*? (?:USING .*?\s)?\(([^]*)\)/gi.exec(row.definition)[1].split(',');
// Map column index in table to column name // Map column index in table to column name
const columns = _.zipObject( const columns = _.zipObject(
result.column_indexes, row.column_indexes,
this.sequelize.queryInterface.QueryGenerator.fromArray(result.column_names) this.sequelize.queryInterface.QueryGenerator.fromArray(row.column_names)
); );
delete result.column_indexes; delete row.column_indexes;
delete result.column_names; delete row.column_names;
let field; let field;
let attribute; let attribute;
// Indkey is the order of attributes in the index, specified by a string of attribute indexes // Indkey is the order of attributes in the index, specified by a string of attribute indexes
result.fields = result.indkey.split(' ').map((indKey, index) => { row.fields = row.indkey.split(' ').map((indKey, index) => {
field = columns[indKey]; field = columns[indKey];
// for functional indices indKey = 0 // for functional indices indKey = 0
if (!field) { if (!field) {
...@@ -165,11 +152,11 @@ class Query extends AbstractQuery { ...@@ -165,11 +152,11 @@ class Query extends AbstractQuery {
length: undefined length: undefined
}; };
}).filter(n => n !== null); }).filter(n => n !== null);
delete result.columns; delete row.columns;
} }
return results; return rows;
} else if (this.isForeignKeysQuery()) { } else if (this.isForeignKeysQuery()) {
result = []; const result = [];
for (const row of rows) { for (const row of rows) {
let defParts; let defParts;
if (row.condef !== undefined && (defParts = row.condef.match(/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?/))) { if (row.condef !== undefined && (defParts = row.condef.match(/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?/))) {
...@@ -188,6 +175,7 @@ class Query extends AbstractQuery { ...@@ -188,6 +175,7 @@ class Query extends AbstractQuery {
} }
return result; return result;
} else if (this.isSelectQuery()) { } else if (this.isSelectQuery()) {
let result = rows;
// Postgres will treat tables as case-insensitive, so fix the case // Postgres will treat tables as case-insensitive, so fix the case
// of the returned values to match attributes // of the returned values to match attributes
if (this.options.raw === false && this.sequelize.options.quoteIdentifiers === false) { if (this.options.raw === false && this.sequelize.options.quoteIdentifiers === false) {
...@@ -195,7 +183,7 @@ class Query extends AbstractQuery { ...@@ -195,7 +183,7 @@ class Query extends AbstractQuery {
m[k.toLowerCase()] = k; m[k.toLowerCase()] = k;
return m; return m;
}, {}); }, {});
rows = _.map(rows, row=> { result = _.map(rows, row=> {
return _.mapKeys(row, (value, key)=> { return _.mapKeys(row, (value, key)=> {
const targetAttr = attrsMap[key]; const targetAttr = attrsMap[key];
if (typeof targetAttr === 'string' && targetAttr !== key) { if (typeof targetAttr === 'string' && targetAttr !== key) {
...@@ -206,34 +194,34 @@ class Query extends AbstractQuery { ...@@ -206,34 +194,34 @@ class Query extends AbstractQuery {
}); });
}); });
} }
return this.handleSelectQuery(rows); return this.handleSelectQuery(result);
} else if (QueryTypes.DESCRIBE === this.options.type) { } else if (QueryTypes.DESCRIBE === this.options.type) {
result = {}; const result = {};
for (const _result of rows) { for (const row of rows) {
result[_result.Field] = { result[row.Field] = {
type: _result.Type.toUpperCase(), type: row.Type.toUpperCase(),
allowNull: _result.Null === 'YES', allowNull: row.Null === 'YES',
defaultValue: _result.Default, defaultValue: row.Default,
special: _result.special ? this.sequelize.queryInterface.QueryGenerator.fromArray(_result.special) : [], special: row.special ? this.sequelize.queryInterface.QueryGenerator.fromArray(row.special) : [],
primaryKey: _result.Constraint === 'PRIMARY KEY' primaryKey: row.Constraint === 'PRIMARY KEY'
}; };
if (result[_result.Field].type === 'BOOLEAN') { if (result[row.Field].type === 'BOOLEAN') {
result[_result.Field].defaultValue = { 'false': false, 'true': true }[result[_result.Field].defaultValue]; result[row.Field].defaultValue = { 'false': false, 'true': true }[result[row.Field].defaultValue];
if (result[_result.Field].defaultValue === undefined) { if (result[row.Field].defaultValue === undefined) {
result[_result.Field].defaultValue = null; result[row.Field].defaultValue = null;
} }
} }
if (typeof result[_result.Field].defaultValue === 'string') { if (typeof result[row.Field].defaultValue === 'string') {
result[_result.Field].defaultValue = result[_result.Field].defaultValue.replace(/'/g, ''); result[row.Field].defaultValue = result[row.Field].defaultValue.replace(/'/g, '');
if (result[_result.Field].defaultValue.indexOf('::') > -1) { if (result[row.Field].defaultValue.indexOf('::') > -1) {
const split = result[_result.Field].defaultValue.split('::'); const split = result[row.Field].defaultValue.split('::');
if (split[1].toLowerCase() !== 'regclass)') { if (split[1].toLowerCase() !== 'regclass)') {
result[_result.Field].defaultValue = split[0]; result[row.Field].defaultValue = split[0];
} }
} }
} }
...@@ -241,17 +229,17 @@ class Query extends AbstractQuery { ...@@ -241,17 +229,17 @@ class Query extends AbstractQuery {
return result; return result;
} else if (this.isVersionQuery()) { } else if (this.isVersionQuery()) {
return results[0].server_version; return rows[0].server_version;
} else if (this.isShowOrDescribeQuery()) { } else if (this.isShowOrDescribeQuery()) {
return results; return rows;
} else if (QueryTypes.BULKUPDATE === this.options.type) { } else if (QueryTypes.BULKUPDATE === this.options.type) {
if (!this.options.returning) { if (!this.options.returning) {
return parseInt(result.rowCount, 10); return parseInt(rowCount, 10);
} }
return this.handleSelectQuery(rows); return this.handleSelectQuery(rows);
} else if (QueryTypes.BULKDELETE === this.options.type) { } else if (QueryTypes.BULKDELETE === this.options.type) {
return parseInt(result.rowCount, 10); return parseInt(rowCount, 10);
} else if (this.isUpsertQuery()) { } else if (this.isUpsertQuery()) {
return rows[0].sequelize_upsert; return rows[0].sequelize_upsert;
} else if (this.isInsertQuery() || this.isUpdateQuery()) { } else if (this.isInsertQuery() || this.isUpdateQuery()) {
...@@ -269,12 +257,12 @@ class Query extends AbstractQuery { ...@@ -269,12 +257,12 @@ class Query extends AbstractQuery {
return [ return [
this.instance || rows && (this.options.plain && rows[0] || rows) || undefined, this.instance || rows && (this.options.plain && rows[0] || rows) || undefined,
result.rowCount rowCount
]; ];
} else if (this.isRawQuery()) { } else if (this.isRawQuery()) {
return [rows, result]; return [rows, queryResult];
} else { } else {
return results; return rows;
} }
}); });
} }
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!