Skip to content

Commit c6bed60

Browse files
fix: consider nulls first | last on orderBy (#1064)
fix #1062
1 parent fcde2f2 commit c6bed60

File tree

4 files changed

+32
-21
lines changed

4 files changed

+32
-21
lines changed

db-service/lib/cqn2sql.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -421,14 +421,15 @@ class CQN2SQLRenderer {
421421
* @returns {string[] | string} SQL
422422
*/
423423
orderBy(orderBy, localized) {
424-
return orderBy.map(
425-
localized
426-
? c =>
427-
this.expr(c) +
424+
return orderBy.map(c => {
425+
const o = localized
426+
? this.expr(c) +
428427
(c.element?.[this.class._localized] ? ' COLLATE NOCASE' : '') +
429428
(c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
430-
: c => this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC'),
431-
)
429+
: this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
430+
if (c.nulls) return o + ' NULLS ' + (c.nulls.toLowerCase() === 'first' ? 'FIRST' : 'LAST')
431+
return o
432+
})
432433
}
433434

434435
/**

hana/lib/HANAService.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -904,17 +904,17 @@ SELECT ${mixing} FROM JSON_TABLE(SRC.JSON, '$' COLUMNS(${extraction})) AS NEW LE
904904
}
905905

906906
orderBy(orderBy, localized) {
907-
return orderBy.map(
908-
localized
909-
? c =>
910-
this.expr(c) +
907+
return orderBy.map(c => {
908+
const o = localized
909+
? this.expr(c) +
911910
(c.element?.[this.class._localized]
912-
? ` COLLATE ${collations[this.context.locale] || collations[this.context.locale.split('_')[0]] || collations['']
913-
}`
911+
? ` COLLATE ${collations[this.context.locale] || collations[this.context.locale.split('_')[0]] || collations['']}`
914912
: '') +
915913
(c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
916-
: c => this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC'),
917-
)
914+
: this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
915+
if (c.nulls) return o + ' NULLS ' + (c.nulls.toLowerCase() === 'first' ? 'FIRST' : 'LAST')
916+
return o
917+
})
918918
}
919919

920920
limit({ rows, offset }) {

postgres/lib/PostgresService.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -344,14 +344,15 @@ GROUP BY k
344344

345345
static CQN2SQL = class CQN2Postgres extends SQLService.CQN2SQL {
346346
_orderBy(orderBy, localized, locale) {
347-
return orderBy.map(
348-
localized
349-
? c =>
350-
this.expr(c) +
347+
return orderBy.map(c => {
348+
const nulls = c.nulls || (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? 'LAST' : 'FIRST')
349+
const o = localized
350+
? this.expr(c) +
351351
(c.element?.[this.class._localized] ? ` COLLATE "${locale}"` : '') +
352-
(c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC NULLS LAST' : ' ASC NULLS FIRST')
353-
: c => this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC NULLS LAST' : ' ASC NULLS FIRST'),
354-
)
352+
(c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
353+
: this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
354+
return o + ' NULLS ' + (nulls.toLowerCase() === 'first' ? 'FIRST' : 'LAST')
355+
})
355356
}
356357

357358
orderBy(orderBy) {

test/scenarios/bookshop/orderBy.test.js

+9
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,13 @@ describe('Bookshop - Order By', () => {
6666
expect(res.length).to.be.eq(1)
6767
expect(res[0].author).to.eq('Charlotte Brontë')
6868
})
69+
70+
test('nulls first | last', async () => {
71+
const { Authors } = cds.entities('sap.capire.bookshop')
72+
await INSERT.into(Authors).entries({ ID: 42, name: 'Brandon Sanderson' }) // dateOfDeath => null
73+
const nullsFirst = await cds.ql`SELECT from ${Authors} { name } order by dateOfDeath asc nulls first`
74+
expect(nullsFirst[0].name).to.eq('Brandon Sanderson')
75+
const nullsLast = await cds.ql`SELECT from ${Authors} { name } order by dateOfDeath asc nulls last`
76+
expect(nullsLast.at(-1).name).to.eq('Brandon Sanderson')
77+
});
6978
})

0 commit comments

Comments
 (0)