@sap/cds
Version:
SAP Cloud Application Programming Model - CDS for Node.js
84 lines (67 loc) • 2.64 kB
JavaScript
const { DRAFT_COLUMNS_MAP } = require('../constants/draft')
const _getStaticOrders = req => {
const { target: entity, query } = req
const ordersFromKeys = []
if (req.target._isSingleton || query.SELECT.limit) {
const keys = [...(entity.keys || [])].filter(k => !k.isAssociation).map(k => k.name)
for (const key of keys) {
if (!(key in DRAFT_COLUMNS_MAP)) {
ordersFromKeys.push({ by: { '=': key }, implicit: true })
}
}
}
if (entity.query && entity.query.SELECT && entity.query.SELECT.orderBy) {
const orderBy = entity.query.SELECT.orderBy
const ordersFromView = orderBy.map(keyName => ({
by: { '=': keyName.ref[keyName.ref.length - 1] },
desc: keyName.sort === 'desc'
}))
return [...ordersFromView, ...ordersFromKeys]
}
return ordersFromKeys
}
const _addDefaultSortOrder = (req, select) => {
// "static orders" = the orders not from the query options
let staticOrders = _getStaticOrders(req)
// remove defaultOrder if not part of group by
const groupBy = select?.groupBy || select?.from?.SELECT?.groupBy
if (groupBy?.length > 0) staticOrders = staticOrders.filter(d => groupBy.some(e => e.ref[0] === d.by['=']))
if (!staticOrders.length) return
if (select?.from?.SELECT?.groupBy?.length > 0) select = select.from.SELECT
select.orderBy = select.orderBy ?? []
select.orderBy.push(
...staticOrders
.filter(d => !select.orderBy.find(o => o.ref && o.ref.join('_') === d.by['=']))
.map(d => {
const orderByRef = { ref: [d.by['=']], sort: d.desc ? 'desc' : 'asc' }
if (d.implicit) orderByRef.implicit = true
return orderByRef
})
)
}
const containsAggregation = column => {
if (column.func) return true
if (column.xpr) return column.xpr.some(xpr => containsAggregation(xpr))
return false
}
/**
* 1. query options --> already set in req.query
* 2. orders from view
* 3. orders from keys if singleton or limit is set
*
* @param req
*/
const handle_sorting = function (req) {
if (!req.query || !req.query.SELECT || req.query.SELECT.one) return
let select = req.query.SELECT
// do not sort for /$count queries or queries only using aggregations
if (select.columns?.length && select.columns.every(col => containsAggregation(col))) return
_addDefaultSortOrder(req, select)
// also apply default sort to bottom-most sub-query
if (select.from?.SELECT) {
while (select.from.SELECT) select = select.from.SELECT
_addDefaultSortOrder(req, select)
}
}
module.exports = () => handle_sorting
module.exports.commonGenericSorting = handle_sorting // needed in lean draft