Skip to content

Commit e343e79

Browse files
fix(expand): proper subquery from construction (#1126)
if a query selects from another query, we need to consider the case where the subquery has path expressions (and therefore joins). The best solution is then to drill down into the innermost query of the from clause, because we do not know the depth. It is also not a good idea to check for the `ref` of the innermost _untransformed_ query, as it is potentially a scoped query (as shown in one of the tests). Moreover, it is not possible to use the `ref` of the _transformed_ query because it might be replaced by join `args`. replaces #1114 fix #1112
1 parent fcab43c commit e343e79

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

db-service/lib/cqn4sql.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,8 +801,9 @@ function cqn4sql(originalQuery, model) {
801801
})
802802
} else {
803803
outerAlias = transformedQuery.SELECT.from.as
804+
const getInnermostTarget = q => q._target ? getInnermostTarget(q._target) : q
804805
subqueryFromRef = [
805-
...(transformedQuery.SELECT.from.ref || /* subq in from */ transformedQuery.SELECT.from.SELECT.from.ref),
806+
...(transformedQuery.SELECT.from.ref || /* subq in from */ [getInnermostTarget(transformedQuery).name]),
806807
...ref,
807808
]
808809
}

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

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,93 @@ describe('Unfold expands on associations to special subselects', () => {
10921092
}`
10931093
expect(JSON.parse(JSON.stringify(cqn4sql(q, model)))).to.eql(expected)
10941094
})
1095+
1096+
it('expand via subquery with path expressions', () => {
1097+
const q = cds.ql`SELECT from (SELECT from bookshop.Books as inner { author, ID } where author.name = 'King') as Outer {
1098+
ID,
1099+
author { name }
1100+
}`
1101+
const res = cqn4sql(q, model)
1102+
const expected = cds.ql`
1103+
SELECT from (
1104+
SELECT from bookshop.Books as inner
1105+
left join bookshop.Authors as author on author.ID = inner.author_ID {
1106+
inner.author_ID,
1107+
inner.ID
1108+
} where author.name = 'King'
1109+
) as Outer
1110+
{
1111+
Outer.ID,
1112+
(
1113+
SELECT from bookshop.Authors as $a {
1114+
$a.name
1115+
}
1116+
where Outer.author_ID = $a.ID
1117+
) as author
1118+
}`
1119+
expect(JSON.parse(JSON.stringify(res))).to.deep.equal(expected)
1120+
})
1121+
it('expand via subquery with path expressions nested', () => {
1122+
const q = cds.ql`SELECT from (SELECT from (SELECT from bookshop.Books as inner { author, ID } where author.name = 'King') as Mid { * }) as Outer {
1123+
ID,
1124+
author { name }
1125+
}`
1126+
const res = cqn4sql(q, model)
1127+
const expected = cds.ql`
1128+
SELECT from (
1129+
SELECT from (
1130+
SELECT from bookshop.Books as inner
1131+
left join bookshop.Authors as author on author.ID = inner.author_ID {
1132+
inner.author_ID,
1133+
inner.ID
1134+
} where author.name = 'King'
1135+
) as Mid {
1136+
Mid.author_ID,
1137+
Mid.ID
1138+
}
1139+
) as Outer
1140+
{
1141+
Outer.ID,
1142+
(
1143+
SELECT from bookshop.Authors as $a {
1144+
$a.name
1145+
}
1146+
where Outer.author_ID = $a.ID
1147+
) as author
1148+
}`
1149+
expect(JSON.parse(JSON.stringify(res))).to.deep.equal(expected)
1150+
})
1151+
it('expand via subquery with path expressions and scoped query', () => {
1152+
const q = cds.ql`SELECT from (SELECT from bookshop.Books:genre as inner { parent, ID } where parent.name = 'Drama') as Outer {
1153+
ID,
1154+
parent { name }
1155+
}`
1156+
const res = cqn4sql(q, model)
1157+
const expected = cds.ql`
1158+
SELECT from (
1159+
SELECT from bookshop.Genres as inner
1160+
left join bookshop.Genres as parent on parent.ID = inner.parent_ID {
1161+
inner.parent_ID,
1162+
inner.ID
1163+
} where
1164+
exists (
1165+
SELECT 1 from bookshop.Books as $B
1166+
where $B.genre_ID = inner.ID
1167+
)
1168+
and parent.name = 'Drama'
1169+
) as Outer
1170+
{
1171+
Outer.ID,
1172+
(
1173+
SELECT from bookshop.Genres as $p {
1174+
$p.name
1175+
}
1176+
where Outer.parent_ID = $p.ID
1177+
) as parent
1178+
}
1179+
`
1180+
expect(JSON.parse(JSON.stringify(res))).to.deep.equal(expected)
1181+
})
10951182
})
10961183

10971184
describe('Expands with aggregations are special', () => {

0 commit comments

Comments
 (0)