Skip to content

Commit b270388

Browse files
committed
fix: fixed sorting to use ASC and DESC for 1 and -1
1 parent 2115f4b commit b270388

File tree

2 files changed

+207
-2
lines changed

2 files changed

+207
-2
lines changed

lib/dialects/base/blocks.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,12 +304,20 @@ module.exports = function (dialect) {
304304

305305
if (isObject(sortItem)) {
306306
return map(keys(sortItem), (key) => {
307-
const direction = sortItem[key];
307+
let direction = sortItem[key];
308308
const field = dialect.buildBlock('term', {
309309
term: key,
310310
type: 'field',
311311
});
312312

313+
// Convert MongoDB-style numeric sort to SQL keywords
314+
if (direction === 1 || direction === '1') {
315+
direction = 'asc';
316+
} else if (direction === -1 || direction === '-1') {
317+
direction = 'desc';
318+
}
319+
// Otherwise use the direction as-is (for 'asc', 'desc', 'ASC', 'DESC')
320+
313321
return field + ' ' + direction;
314322
}).join(', ');
315323
}
@@ -325,12 +333,20 @@ module.exports = function (dialect) {
325333
return (
326334
'order by ' +
327335
map(keys(sort), (key) => {
328-
const direction = sort[key];
336+
let direction = sort[key];
329337
const field = dialect.buildBlock('term', {
330338
term: key,
331339
type: 'field',
332340
});
333341

342+
// Convert MongoDB-style numeric sort to SQL keywords
343+
if (direction === 1 || direction === '1') {
344+
direction = 'asc';
345+
} else if (direction === -1 || direction === '-1') {
346+
direction = 'desc';
347+
}
348+
// Otherwise use the direction as-is (for 'asc', 'desc', 'ASC', 'DESC')
349+
334350
return field + ' ' + direction;
335351
}).join(', ')
336352
);

tests/mongodb-sort.test.js

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/* eslint-disable camelcase */
2+
const test = require('ava');
3+
const {Builder} = require('../lib/index.js');
4+
5+
test('sort with MongoDB-style -1 (descending) in object format', t => {
6+
const builder = new Builder();
7+
const sql = builder.build({
8+
type: 'select',
9+
table: 'Messages',
10+
fields: ['*'],
11+
sort: {created_at: -1},
12+
});
13+
14+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
15+
});
16+
17+
test('sort with MongoDB-style 1 (ascending) in object format', t => {
18+
const builder = new Builder();
19+
const sql = builder.build({
20+
type: 'select',
21+
table: 'Messages',
22+
fields: ['*'],
23+
sort: {created_at: 1},
24+
});
25+
26+
t.is(sql.query, 'select * from "Messages" order by "created_at" asc');
27+
});
28+
29+
test('sort with string "-1" (descending) in object format', t => {
30+
const builder = new Builder();
31+
const sql = builder.build({
32+
type: 'select',
33+
table: 'Messages',
34+
fields: ['*'],
35+
sort: {created_at: '-1'},
36+
});
37+
38+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
39+
});
40+
41+
test('sort with string "1" (ascending) in object format', t => {
42+
const builder = new Builder();
43+
const sql = builder.build({
44+
type: 'select',
45+
table: 'Messages',
46+
fields: ['*'],
47+
sort: {created_at: '1'},
48+
});
49+
50+
t.is(sql.query, 'select * from "Messages" order by "created_at" asc');
51+
});
52+
53+
test('sort with multiple fields using MongoDB-style numeric values', t => {
54+
const builder = new Builder();
55+
const sql = builder.build({
56+
type: 'select',
57+
table: 'table',
58+
sort: {a: 1, b: -1},
59+
});
60+
61+
t.is(sql.query, 'select * from "table" order by "a" asc, "b" desc');
62+
});
63+
64+
test('sort with string "desc" for backward compatibility', t => {
65+
const builder = new Builder();
66+
const sql = builder.build({
67+
type: 'select',
68+
table: 'Messages',
69+
fields: ['*'],
70+
sort: {created_at: 'desc'},
71+
});
72+
73+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
74+
});
75+
76+
test('sort with string "asc" for backward compatibility', t => {
77+
const builder = new Builder();
78+
const sql = builder.build({
79+
type: 'select',
80+
table: 'Messages',
81+
fields: ['*'],
82+
sort: {created_at: 'asc'},
83+
});
84+
85+
t.is(sql.query, 'select * from "Messages" order by "created_at" asc');
86+
});
87+
88+
test('sort with array format containing MongoDB-style numeric values', t => {
89+
const builder = new Builder();
90+
const sql = builder.build({
91+
type: 'select',
92+
table: 'table',
93+
sort: [{a: -1}, {b: 1}],
94+
});
95+
96+
t.is(sql.query, 'select * from "table" order by "a" desc, "b" asc');
97+
});
98+
99+
test('sort with limit and offset using MongoDB-style -1', t => {
100+
const builder = new Builder();
101+
const sql = builder.build({
102+
type: 'select',
103+
table: 'Messages',
104+
fields: ['*'],
105+
limit: 10,
106+
offset: 0,
107+
sort: {created_at: -1},
108+
});
109+
110+
t.is(
111+
sql.query,
112+
'select * from "Messages" order by "created_at" desc limit 10 offset 0',
113+
);
114+
});
115+
116+
test('sort with limit and offset using MongoDB-style 1', t => {
117+
const builder = new Builder();
118+
const sql = builder.build({
119+
type: 'select',
120+
table: 'Messages',
121+
fields: ['*'],
122+
limit: 10,
123+
offset: 0,
124+
sort: {created_at: 1},
125+
});
126+
127+
t.is(
128+
sql.query,
129+
'select * from "Messages" order by "created_at" asc limit 10 offset 0',
130+
);
131+
});
132+
133+
test('sort with mixed string and numeric values', t => {
134+
const builder = new Builder();
135+
const sql = builder.build({
136+
type: 'select',
137+
table: 'table',
138+
sort: {a: 1, b: 'desc', c: -1, d: 'asc'},
139+
});
140+
141+
t.is(
142+
sql.query,
143+
'select * from "table" order by "a" asc, "b" desc, "c" desc, "d" asc',
144+
);
145+
});
146+
147+
test('sort with PostgreSQL dialect using MongoDB-style values', t => {
148+
const builder = new Builder({dialect: 'postgresql'});
149+
const sql = builder.build({
150+
type: 'select',
151+
table: 'Messages',
152+
sort: {created_at: -1},
153+
});
154+
155+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
156+
});
157+
158+
test('sort with MySQL dialect using MongoDB-style values', t => {
159+
const builder = new Builder({dialect: 'mysql'});
160+
const sql = builder.build({
161+
type: 'select',
162+
table: 'Messages',
163+
sort: {created_at: -1},
164+
});
165+
166+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
167+
});
168+
169+
test('sort with SQLite dialect using MongoDB-style values', t => {
170+
const builder = new Builder({dialect: 'sqlite'});
171+
const sql = builder.build({
172+
type: 'select',
173+
table: 'Messages',
174+
sort: {created_at: -1},
175+
});
176+
177+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
178+
});
179+
180+
test('sort with MSSQL dialect using MongoDB-style values', t => {
181+
const builder = new Builder({dialect: 'mssql'});
182+
const sql = builder.build({
183+
type: 'select',
184+
table: 'Messages',
185+
sort: {created_at: -1},
186+
});
187+
188+
t.is(sql.query, 'select * from "Messages" order by "created_at" desc');
189+
});

0 commit comments

Comments
 (0)