Skip to content
This repository was archived by the owner on Sep 2, 2025. It is now read-only.

Commit f127b16

Browse files
author
Dekel Barzilay
committed
Added support for GROUP BY with ONLY_FULL_GROUP_BY enabled
1 parent 5deda8e commit f127b16

File tree

3 files changed

+63
-17
lines changed

3 files changed

+63
-17
lines changed

src/index.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,22 @@ class Service extends AdapterService {
275275
}
276276
}
277277

278+
getGroupByColumns (query) {
279+
for (const operation of query._operations) {
280+
if (operation.name === 'groupBy') {
281+
const args = operation.args;
282+
283+
return Array.isArray(args[0]) ? args[0] : args;
284+
}
285+
}
286+
287+
return null;
288+
}
289+
278290
_createQuery (params = {}) {
279291
const trx = params.transaction ? params.transaction.trx : null;
280292
const schema = params.schema || this.schema;
281-
let query = this.Model.query(trx);
293+
const query = this.Model.query(trx);
282294

283295
return schema ? query.withSchema(schema) : query;
284296
}
@@ -319,10 +331,10 @@ class Service extends AdapterService {
319331
delete query.$joinEager;
320332
}
321333

322-
if (query && query.$joinRelation) {
323-
q
324-
.distinct(`${this.Model.tableName}.*`)
325-
.joinRelated(query.$joinRelation);
334+
const joinRelation = query && query.$joinRelation;
335+
336+
if (joinRelation) {
337+
q.joinRelated(query.$joinRelation);
326338

327339
delete query.$joinRelation;
328340
}
@@ -339,6 +351,12 @@ class Service extends AdapterService {
339351
delete query.$modify;
340352
}
341353

354+
if (joinRelation) {
355+
const groupByColumns = this.getGroupByColumns(q);
356+
357+
if (!groupByColumns) { q.distinct(`${this.Model.tableName}.*`); }
358+
}
359+
342360
// apply eager filters if specified
343361
if (this.eagerFilters) {
344362
const eagerFilters = Array.isArray(this.eagerFilters) ? this.eagerFilters : [this.eagerFilters];
@@ -382,6 +400,7 @@ class Service extends AdapterService {
382400
_find (params) {
383401
const find = (params, count, filters, query) => {
384402
const q = params.objection || this.createQuery(params);
403+
const groupByColumns = this.getGroupByColumns(q);
385404

386405
// Handle $limit
387406
if (filters.$limit) {
@@ -416,18 +435,17 @@ class Service extends AdapterService {
416435
}
417436

418437
if (count) {
419-
const idColumns = Array.isArray(this.id) ? this.id.map(idKey => `${this.Model.tableName}.${idKey}`) : [`${this.Model.tableName}.${this.id}`];
420-
438+
const countColumns = groupByColumns || (Array.isArray(this.id) ? this.id.map(idKey => `${this.Model.tableName}.${idKey}`) : [`${this.Model.tableName}.${this.id}`]);
421439
const countQuery = this._createQuery(params);
422440

423441
if (query.$joinRelation) {
424442
countQuery
425443
.joinRelated(query.$joinRelation)
426-
.countDistinct({ total: idColumns });
427-
} else if (idColumns.length > 1) {
428-
countQuery.countDistinct({ total: idColumns });
444+
.countDistinct({ total: countColumns });
445+
} else if (countColumns.length > 1) {
446+
countQuery.countDistinct({ total: countColumns });
429447
} else {
430-
countQuery.count({ total: idColumns });
448+
countQuery.count({ total: countColumns });
431449
}
432450

433451
if (query && query.$modify) {

test/company.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ export default class Company extends Model {
3838
builder.orderBy('name');
3939
},
4040
google: (builder, hasCeo) => {
41-
builder.where('name', 'Google')
42-
.groupBy(['name']);
41+
builder.where('companies.name', 'Google')
42+
.select(['companies.name'])
43+
.groupBy(['companies.name']);
4344

4445
if (hasCeo) { builder.whereNot('ceo', null); }
4546
},

test/index.test.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,8 +1701,10 @@ describe('Feathers Objection Service', () => {
17011701
});
17021702

17031703
describe('$modify', () => {
1704-
before(async () => {
1705-
await companies
1704+
const ids = {};
1705+
1706+
beforeEach(async () => {
1707+
ids.companies = await companies
17061708
.create([
17071709
{
17081710
name: 'Google',
@@ -1715,13 +1717,25 @@ describe('Feathers Objection Service', () => {
17151717
size: 'large'
17161718
}
17171719
]);
1720+
1721+
ids.employees = await employees
1722+
.create([
1723+
{
1724+
name: 'John',
1725+
companyId: ids.companies[0].id
1726+
},
1727+
{
1728+
name: 'Apple',
1729+
companyId: ids.companies[1].id
1730+
}
1731+
]);
17181732
});
17191733

17201734
afterEach(async () => {
17211735
companies.options.paginate = {};
1722-
});
17231736

1724-
after(async () => {
1737+
for (const employee of ids.employees) { await employees.remove(employee.id); }
1738+
17251739
await companies.remove(null);
17261740
});
17271741

@@ -1757,6 +1771,19 @@ describe('Feathers Objection Service', () => {
17571771
});
17581772
});
17591773

1774+
it('allow $modify query with paginate and groupBy', () => {
1775+
companies.options.paginate = {
1776+
default: 1,
1777+
max: 2
1778+
};
1779+
1780+
return companies.find({ query: { $modify: ['google'], $joinRelation: 'employees' } }).then(data => {
1781+
expect(data.total).to.be.equal(1);
1782+
expect(data.data.length).to.be.equal(1);
1783+
expect(data.data[0].name).to.be.equal('Google');
1784+
});
1785+
});
1786+
17601787
it('allow $modify query as string', () => {
17611788
return companies.find({ query: { $modify: 'google' } }).then(data => {
17621789
expect(data.length).to.be.equal(1);

0 commit comments

Comments
 (0)