Skip to content

Commit

Permalink
orderBy accepts QueryBuilder (#3491)
Browse files Browse the repository at this point in the history
  • Loading branch information
HurSungYun authored and kibertoad committed Oct 24, 2019
1 parent 048900f commit 2d04591
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 4 deletions.
17 changes: 13 additions & 4 deletions lib/query/compiler.js
Expand Up @@ -2,6 +2,7 @@
// -------
const helpers = require('../helpers');
const Raw = require('../raw');
const QueryBuilder = require('./builder');
const JoinClause = require('./joinclause');
const debug = require('debug');

Expand Down Expand Up @@ -823,16 +824,24 @@ assign(QueryCompiler.prototype, {
return vals;
},

_formatGroupsItemValue(value) {
const { formatter } = this;
if (value instanceof Raw) {
return formatter.unwrapRaw(value);
} else if (value instanceof QueryBuilder) {
return '(' + formatter.columnize(value) + ')';
} else {
return formatter.columnize(value);
}
},

// Compiles the `order by` statements.
_groupsOrders(type) {
const items = this.grouped[type];
if (!items) return '';
const { formatter } = this;
const sql = items.map((item) => {
const column =
item.value instanceof Raw
? formatter.unwrapRaw(item.value)
: formatter.columnize(item.value);
const column = this._formatGroupsItemValue(item.value);
const direction =
type === 'order' && item.type !== 'orderByRaw'
? ` ${formatter.direction(item.direction)}`
Expand Down
37 changes: 37 additions & 0 deletions test/unit/query/builder.js
Expand Up @@ -3176,6 +3176,43 @@ describe('QueryBuilder', () => {
);
});

it('order by accepts query builder', () => {
testsql(
qb()
.select()
.from('persons')
.orderBy(
qb()
.select()
.from('persons as p')
.whereColumn('persons.id', 'p.id')
.select('p.id')
),
{
mysql: {
sql:
'select * from `persons` order by (select `p`.`id` from `persons` as `p` where `persons`.`id` = `p`.`id`) asc',
bindings: [],
},
mssql: {
sql:
'select * from [persons] order by (select [p].[id] from [persons] as [p] where [persons].[id] = [p].[id]) asc',
bindings: [],
},
pg: {
sql:
'select * from "persons" order by (select "p"."id" from "persons" as "p" where "persons"."id" = "p"."id") asc',
bindings: [],
},
sqlite3: {
sql:
'select * from `persons` order by (select `p`.`id` from `persons` as `p` where `persons`.`id` = `p`.`id`) asc',
bindings: [],
},
}
);
});

it('raw group bys', () => {
testsql(
qb()
Expand Down
3 changes: 3 additions & 0 deletions types/index.d.ts
Expand Up @@ -1197,6 +1197,9 @@ declare namespace Knex {
(
columnDefs: Array<string | { column: string; order?: string }>
): QueryBuilder<TRecord, TResult>;
<TRecordInner, TResultInner>(
subQueryBuilder: QueryBuilder<TRecordInner, TResultInner>
): QueryBuilder<TRecord, TResult>;
}

interface Intersect<TRecord = any, TResult = unknown[]> {
Expand Down
10 changes: 10 additions & 0 deletions types/test.ts
Expand Up @@ -492,6 +492,16 @@ const main = async () => {
.orderBy('name', 'desc')
.havingRaw('age > ?', [10]);

// $ExpectType User[]
await knex<User>('users')
.select()
.orderBy(
knex<User>('users')
.select('u.id')
.from('users as u')
.where('users.id', 'u.id')
);

// $ExpectType Dict<string | number>[]
await knex<User>('users').count();

Expand Down

0 comments on commit 2d04591

Please sign in to comment.