Skip to content

Commit bbe7be0

Browse files
fix: wildcard expand with aggregation (#923)
for the case where we `group by` expanded columns, we must ignore the `expand` from the columns
1 parent 2c72c87 commit bbe7be0

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

db-service/lib/cqn4sql.js

+10-7
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ function cqn4sql(originalQuery, model) {
408408
const last = $refLinks?.[$refLinks.length - 1]
409409
if (last && !last.skipExpand && last.definition.isAssociation) {
410410
const expandedSubqueryColumn = expandColumn(col)
411+
if (!expandedSubqueryColumn) return []
411412
setElementOnColumns(expandedSubqueryColumn, col.element)
412413
res.push(expandedSubqueryColumn)
413414
} else if (!last?.skipExpand) {
@@ -863,7 +864,7 @@ function cqn4sql(originalQuery, model) {
863864
* @param {Object} column - To expand.
864865
* @param {Array} baseRef - The base reference for the expanded column.
865866
* @param {string} subqueryAlias - The alias of the `expand` subquery column.
866-
* @returns {Object} - The subquery object.
867+
* @returns {Object} - The subquery object or null if the expand has a wildcard.
867868
* @throws {Error} - If one of the `ref`s in the `column.expand` is not part of the GROUP BY clause.
868869
*/
869870
function _subqueryForGroupBy(column, baseRef, subqueryAlias) {
@@ -873,7 +874,13 @@ function cqn4sql(originalQuery, model) {
873874

874875
// to be attached to dummy query
875876
const elements = {}
877+
const wildcardIndex = column.expand.findIndex(e => e === '*')
878+
if (wildcardIndex !== -1) {
879+
// expand with wildcard vanishes as expand is part of the group by (OData $apply + $expand)
880+
return null
881+
}
876882
const expandedColumns = column.expand.flatMap(expand => {
883+
if (!expand.ref) return expand
877884
const fullRef = [...baseRef, ...expand.ref]
878885

879886
if (expand.expand) {
@@ -1404,8 +1411,7 @@ function cqn4sql(originalQuery, model) {
14041411
if (list.every(e => e.val))
14051412
// no need for transformation
14061413
transformedTokenStream.push({ list })
1407-
else
1408-
transformedTokenStream.push({ list: getTransformedTokenStream(list, $baseLink) })
1414+
else transformedTokenStream.push({ list: getTransformedTokenStream(list, $baseLink) })
14091415
}
14101416
} else if (tokenStream.length === 1 && token.val && $baseLink) {
14111417
// infix filter - OData variant w/o mentioning key --> flatten out and compare each leaf to token.val
@@ -2204,10 +2210,7 @@ function cqn4sql(originalQuery, model) {
22042210
const xpr = search
22052211
const searchFunc = {
22062212
func: 'search',
2207-
args: [
2208-
{ list: searchIn },
2209-
xpr.length === 1 && 'val' in xpr[0] ? xpr[0] : { xpr },
2210-
],
2213+
args: [{ list: searchIn }, xpr.length === 1 && 'val' in xpr[0] ? xpr[0] : { xpr }],
22112214
}
22122215
return searchFunc
22132216
} else {

db-service/test/cqn4sql/expand.test.js

+29
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,35 @@ describe('Expands with aggregations are special', () => {
10501050
const res = cqn4sql(q, model)
10511051
expect(JSON.parse(JSON.stringify(res))).to.deep.equal(qx)
10521052
})
1053+
it.skip('simple aggregation expand ref wrapped in func', () => {
1054+
// TODO: how to detect the nested ref?
1055+
const q = CQL`SELECT from bookshop.Books {
1056+
ID,
1057+
Books.author { toLower(name) as lower }
1058+
} group by author.name`
1059+
1060+
const qx = CQL`SELECT from bookshop.Books as Books left join bookshop.Authors as author on author.ID = Books.author_ID {
1061+
Books.ID,
1062+
(SELECT from DUMMY { toLower(author.name) as name }) as author
1063+
} group by author.name`
1064+
qx.SELECT.columns[1].SELECT.from = null
1065+
const res = cqn4sql(q, model)
1066+
expect(JSON.parse(JSON.stringify(res))).to.deep.equal(qx)
1067+
})
1068+
1069+
it('wildcard expand vanishes for aggregations', () => {
1070+
const q = CQL`SELECT from bookshop.TestPublisher {
1071+
ID
1072+
} group by ID, publisher.structuredKey_ID, publisher.title`
1073+
1074+
const qx = CQL`SELECT from bookshop.TestPublisher as TestPublisher
1075+
left join bookshop.Publisher as publisher on publisher.structuredKey_ID = TestPublisher.publisher_structuredKey_ID {
1076+
TestPublisher.ID
1077+
} group by TestPublisher.ID, TestPublisher.publisher_structuredKey_ID, publisher.title`
1078+
// the key is not flat in the model so we use a flat csn for this test
1079+
const res = cqn4sql(q, cds.compile.for.nodejs(model))
1080+
expect(JSON.parse(JSON.stringify(res))).to.deep.equal(qx)
1081+
})
10531082
it('aggregation with structure', () => {
10541083
const q = CQL`SELECT from bookshop.Authors as Authors {
10551084
ID,

0 commit comments

Comments
 (0)