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

Commit d2f33830 by Mike Sadowski Committed by Sushant

feat(postgres): support returning attributes with bulkCreate (#11170)

1 parent f3b5f99b
...@@ -170,6 +170,32 @@ User.bulkCreate([ ...@@ -170,6 +170,32 @@ User.bulkCreate([
}) })
``` ```
Insert several rows and return all columns (Postgres only):
```js
User.bulkCreate([
{ username: 'barfooz', isAdmin: true },
{ username: 'foo', isAdmin: true },
{ username: 'bar', isAdmin: false }
], { returning: true }) // will return all columns for each row inserted
.then((result) => {
console.log(result);
});
```
Insert several rows and return specific columns (Postgres only):
```js
User.bulkCreate([
{ username: 'barfooz', isAdmin: true },
{ username: 'foo', isAdmin: true },
{ username: 'bar', isAdmin: false }
], { returning: ['username'] }) // will return only the specified columns for each row inserted
.then((result) => {
console.log(result);
});
```
To update several rows at once: To update several rows at once:
```js ```js
......
...@@ -313,8 +313,15 @@ class QueryGenerator { ...@@ -313,8 +313,15 @@ class QueryGenerator {
const ignoreDuplicates = options.ignoreDuplicates ? this._dialect.supports.inserts.ignoreDuplicates : ''; const ignoreDuplicates = options.ignoreDuplicates ? this._dialect.supports.inserts.ignoreDuplicates : '';
const attributes = allAttributes.map(attr => this.quoteIdentifier(attr)).join(','); const attributes = allAttributes.map(attr => this.quoteIdentifier(attr)).join(',');
const returning = this._dialect.supports.returnValues && options.returning ? ' RETURNING *' : '';
const onConflictDoNothing = options.ignoreDuplicates ? this._dialect.supports.inserts.onConflictDoNothing : ''; const onConflictDoNothing = options.ignoreDuplicates ? this._dialect.supports.inserts.onConflictDoNothing : '';
let returning = '';
if (this._dialect.supports.returnValues && Array.isArray(options.returning)) {
const fields = options.returning.map(field => this.quoteIdentifier(field)).join(',');
returning += ` RETURNING ${fields}`;
} else {
returning += this._dialect.supports.returnValues && options.returning ? ' RETURNING *' : '';
}
return `INSERT${ignoreDuplicates} INTO ${this.quoteTable(tableName)} (${attributes}) VALUES ${tuples.join(',')}${onDuplicateKeyUpdate}${onConflictDoNothing}${returning};`; return `INSERT${ignoreDuplicates} INTO ${this.quoteTable(tableName)} (${attributes}) VALUES ${tuples.join(',')}${onDuplicateKeyUpdate}${onConflictDoNothing}${returning};`;
} }
......
...@@ -2522,7 +2522,7 @@ class Model { ...@@ -2522,7 +2522,7 @@ class Model {
* @param {Transaction} [options.transaction] Transaction to run query under * @param {Transaction} [options.transaction] Transaction to run query under
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql. * @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {boolean} [options.benchmark=false] Pass query execution time in milliseconds as second argument to logging function (options.logging). * @param {boolean} [options.benchmark=false] Pass query execution time in milliseconds as second argument to logging function (options.logging).
* @param {boolean} [options.returning=false] Append RETURNING * to get back auto generated values (Postgres only) * @param {boolean|Array} [options.returning=false] If true, append RETURNING * to get back all values; if an array of column names, append RETURNING <columns> to get back specific columns (Postgres only)
* @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only) * @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
* *
* @returns {Promise<Array<Model>>} * @returns {Promise<Array<Model>>}
...@@ -2652,6 +2652,11 @@ class Model { ...@@ -2652,6 +2652,11 @@ class Model {
} }
} }
// Map returning attributes to fields
if (options.returning && Array.isArray(options.returning)) {
options.returning = options.returning.map(attr => this.rawAttributes[attr].field || attr);
}
return this.QueryInterface.bulkInsert(this.getTableName(options), records, options, fieldMappedAttributes).then(results => { return this.QueryInterface.bulkInsert(this.getTableName(options), records, options, fieldMappedAttributes).then(results => {
if (Array.isArray(results)) { if (Array.isArray(results)) {
results.forEach((result, i) => { results.forEach((result, i) => {
......
...@@ -819,6 +819,9 @@ if (dialect.startsWith('postgres')) { ...@@ -819,6 +819,9 @@ if (dialect.startsWith('postgres')) {
arguments: ['myTable', [{ name: 'foo' }, { name: 'bar' }], { returning: true }], arguments: ['myTable', [{ name: 'foo' }, { name: 'bar' }], { returning: true }],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;"
}, { }, {
arguments: ['myTable', [{ name: 'foo' }, { name: 'bar' }], { returning: ['id', 'sentToId'] }],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING \"id\",\"sentToId\";"
}, {
arguments: ['myTable', [{ name: 'foo' }, { name: 'bar' }], { ignoreDuplicates: true, returning: true }], arguments: ['myTable', [{ name: 'foo' }, { name: 'bar' }], { ignoreDuplicates: true, returning: true }],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') ON CONFLICT DO NOTHING RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') ON CONFLICT DO NOTHING RETURNING *;"
}, { }, {
......
...@@ -741,9 +741,9 @@ export interface BulkCreateOptions extends Logging, Transactionable { ...@@ -741,9 +741,9 @@ export interface BulkCreateOptions extends Logging, Transactionable {
updateOnDuplicate?: string[]; updateOnDuplicate?: string[];
/** /**
* Return the affected rows (only for postgres) * Return all columns or only the specified columns for the affected rows (only for postgres)
*/ */
returning?: boolean; returning?: boolean | string[];
} }
/** /**
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!