Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Commit f599206

Browse files
danjoachgeo
andauthored
Fixed cds.ql in latest release (#232)
* Fixed cds.ql in latest release * Requires @sap/cds ^5.1.5 * fixed fixes * More cdr tests Co-authored-by: Christian Georgi <[email protected]>
1 parent 2f5d159 commit f599206

File tree

3 files changed

+159
-164
lines changed

3 files changed

+159
-164
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
"@capire/media": "./media",
1313
"@capire/orders": "./orders",
1414
"@capire/reviews": "./reviews",
15-
"@sap/cds": "^5",
16-
"express": "^4"
15+
"@sap/cds": "^5.1.5"
1716
},
1817
"devDependencies": {
1918
"cds-swagger-ui-express": "^0.2.0",

test/cds.ql.test.js

Lines changed: 153 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
const cds = require('@sap/cds/lib')
22
const { expect } = cds.test
3-
const CQL = ([cql]) => cds.parse.cql(cql)
3+
const { cdr } = cds.ql
44
const Foo = { name: 'Foo' }
55
const Books = { name: 'capire.bookshop.Books' }
66

7-
const { cdr } = cds.ql
87

9-
// while jest has 'test' as alias to 'it', mocha doesn't
10-
if (!global.test) global.test = it
8+
const STAR = cdr ? '*' : { ref: ['*'] }
9+
const skip = {to:{eql:()=>skip}}
10+
const srv = new cds.Service
11+
let cqn
12+
13+
expect.plain = (cqn) => !cqn.SELECT.one && !cqn.SELECT.distinct ? expect(cqn) : skip
14+
expect.one = (cqn) => !cqn.SELECT.distinct ? expect(cqn) : skip
1115

1216
describe('cds.ql → cqn', () => {
1317
//
14-
let cqn
1518

1619
describe(`SELECT...`, () => {
1720

@@ -26,210 +29,206 @@ describe('cds.ql → cqn', () => {
2629
.to.eql(SELECT.from(Foo,['*']))
2730
})
2831

29-
test('from ( Foo )', () => {
30-
expect({
32+
33+
it('should consistently handle lists', () => {
34+
const ID = 11, args = [{ref:['foo']}, 'bar', 3]
35+
const cqn = CQL`SELECT from Foo where ID=11 and x in (foo,'bar',3)`
36+
expect(SELECT.from`Foo`.where `ID=${ID} and x in ${args}`).to.eql(cqn)
37+
expect(SELECT.from(Foo).where(`ID=`, ID, `and x in`, args)).to.eql(cqn)
38+
expect(SELECT.from(Foo).where({ ID, x:args })).to.eql(cqn)
39+
})
40+
41+
})
42+
43+
44+
for (let each of ['SELECT', 'SELECT one', 'SELECT distinct']) {
45+
let SELECT; beforeEach(()=> SELECT = (
46+
each === 'SELECT distinct' ? cds.ql.SELECT.distinct :
47+
each === 'SELECT one' ? cds.ql.SELECT.one :
48+
cds.ql.SELECT
49+
))
50+
describe(`${each}...`, () => {
51+
52+
test(`from Foo`, () => {
53+
expect(cqn = SELECT `from Foo`)
54+
.to.eql(SELECT.from `Foo`)
55+
.to.eql(SELECT.from('Foo'))
56+
.to.eql(SELECT.from(Foo))
57+
.to.eql(SELECT`Foo`)
58+
.to.eql(SELECT('Foo'))
59+
.to.eql(SELECT(Foo))
60+
expect.plain(cqn)
61+
.to.eql(CQL`SELECT from Foo`)
62+
.to.eql(srv.read `Foo`)
63+
.to.eql(srv.read('Foo'))
64+
.to.eql(srv.read(Foo))
65+
.to.eql({
3166
SELECT: { from: { ref: ['Foo'] } },
3267
})
33-
.to.eql(CQL`SELECT from Foo`)
34-
.to.eql(SELECT.from(Foo))
3568
})
3669

37-
test('from ( ..., <key>)', () => {
38-
// Compiler
39-
expect(CQL`SELECT from Foo[11]`).to.eql({
40-
SELECT: {
41-
// REVISIT: add one:true?
42-
from: { ref: [{ id: 'Foo', where: [{ val: 11 }] }] },
43-
},
70+
71+
test('from Foo [<key>]', () => {
72+
73+
expect(cqn = SELECT`from Foo[11]`)
74+
.to.eql(SELECT`from Foo[${11}]`)
75+
.to.eql(SELECT.from `Foo[11]`)
76+
.to.eql(SELECT.from `Foo[${11}]`)
77+
.to.eql(SELECT`Foo[11]`)
78+
expect.plain(cqn)
79+
.to.eql(CQL`SELECT from Foo[11]`)
80+
.to.eql(srv.read`Foo[11]`)
81+
.to.eql({
82+
SELECT: { from: {
83+
ref: [{ id: 'Foo', where: [{ val: 11 }] }]
84+
}},
4485
})
4586

46-
expect(CQL`SELECT from Foo[ID=11]`).to.eql({
47-
SELECT: {
48-
// REVISIT: add one:true
49-
from: {
50-
ref: [{ id: 'Foo', where: [{ ref: ['ID'] }, '=', { val: 11 }] }],
51-
},
52-
},
87+
if (cdr) expect.plain (cqn)
88+
.to.eql(srv.read`Foo[${11}]`)
89+
.to.eql(SELECT`Foo[${11}]`)
90+
91+
expect((cqn = SELECT`from Foo[ID=11]`))
92+
.to.eql(SELECT`from Foo[ID=${11}]`)
93+
.to.eql(SELECT.from `Foo[ID=11]`)
94+
.to.eql(SELECT.from `Foo[ID=${11}]`)
95+
.to.eql(SELECT`Foo[ID=11]`)
96+
expect.plain(cqn)
97+
.to.eql(CQL`SELECT from Foo[ID=11]`)
98+
.to.eql(srv.read`Foo[ID=11]`)
99+
.to.eql({
100+
SELECT: { from: {
101+
ref: [{ id: 'Foo', where: [{ ref: ['ID'] }, '=', { val: 11 }] }],
102+
}},
53103
})
54104

55-
// Runtime ds.ql
56-
expect(SELECT.from(Foo, 11))
57-
.to.eql(SELECT.from(Foo, { ID: 11 }))
58-
.to.eql(SELECT.from(Foo).byKey(11))
59-
.to.eql(SELECT.from(Foo).byKey({ ID: 11 }))
60-
.to.eql(SELECT.one.from(Foo).where({ ID: 11 }))
61-
.to.eql({
62-
// REVISIT: should produce CQN as the ones above?
63-
SELECT: {
64-
one: true,
65-
from: { ref: ['Foo'] },
66-
where: [{ ref: ['ID'] }, '=', { val: 11 }],
67-
},
68-
})
105+
if (cdr) expect.plain (cqn)
106+
.to.eql(SELECT`Foo[ID=${11}]`)
107+
.to.eql(srv.read`Foo[ID=${11}]`)
69108

70-
expect(CQL`SELECT from Foo[11]{a}`).to.eql({
109+
// Following implicitly resolve to SELECT.one
110+
expect(cqn = SELECT.from(Foo,11))
111+
.to.eql(SELECT.from(Foo,{ID:11}))
112+
.to.eql(SELECT.from(Foo).byKey(11))
113+
.to.eql(SELECT.from(Foo).byKey({ID:11}))
114+
expect.one(cqn)
115+
.to.eql({
71116
SELECT: {
72-
// REVISIT: add one:true?
73-
from: { ref: [{ id: 'Foo', where: [{ val: 11 }] }] },
74-
columns: [{ ref: ['a'] }],
117+
one: true,
118+
from: { ref: ['Foo'] },
119+
where: [{ ref: ['ID'] }, '=', { val: 11 }],
75120
},
76121
})
77122

78-
expect(SELECT.from(Foo, 11, ['a']))
79-
.to.eql(SELECT.from(Foo, 11, (foo) => foo.a))
80-
.to.eql({
81-
// REVISIT: should produce CQN as the ones above?
82-
SELECT: {
83-
one: true,
84-
from: { ref: ['Foo'] },
85-
columns: [{ ref: ['a'] }],
86-
where: [{ ref: ['ID'] }, '=', { val: 11 }],
87-
},
88-
})
89123
})
90124

91-
test('from ( ..., => {...})', () => {
92-
// single *, prefix and postfix, as array and function
93-
let parsed, fluid
94-
expect((parsed = CQL`SELECT * from Foo`)).to.eql(CQL`SELECT from Foo{*}`)
95-
//> .to.eql... FIXME: see skipped 'should handle * correctly' below
96-
expect((fluid = SELECT('*').from(Foo)))
97-
.to.eql(SELECT.from(Foo, ['*']))
98-
.to.eql(SELECT.from(Foo, (foo) => foo('*')))
99-
.to.eql(SELECT.from(Foo).columns('*'))
100-
.to.eql(SELECT.from(Foo).columns((foo) => foo('*')))
101-
.to.eql({
102-
SELECT: { from: { ref: ['Foo'] }, columns: [cdr ? '*' : { ref: ['*'] }] },
103-
})
104-
105-
if (cdr === 'all') expect(parsed).to.eql(fluid)
106-
107-
// single column, prefix and postfix, as array and function
108-
expect(CQL`SELECT a from Foo`)
109-
expect(CQL`SELECT from Foo {a}`)
110-
.to.eql(SELECT.from(Foo, ['a']))
111-
.to.eql(SELECT.from(Foo, (foo) => foo.a))
112-
.to.eql({
113-
SELECT: { from: { ref: ['Foo'] }, columns: [{ ref: ['a'] }] },
114-
})
115-
116-
// multiple columns, prefix and postfix, as array and function
117-
expect(CQL`SELECT a,b as c from Foo`)
118-
119-
expect (CQL`SELECT from Foo {a,b as c}`).to.eql(cqn = {
125+
test('from Foo {...}', () => {
126+
127+
expect(cqn = SELECT `*,a,b as c` .from `Foo`)
128+
.to.eql(SELECT `*,a,b as c`. from(Foo))
129+
.to.eql(SELECT('*','a',{b:'c'}).from`Foo`)
130+
.to.eql(SELECT('*','a',{b:'c'}).from(Foo))
131+
.to.eql(SELECT(['*','a',{b:'c'}]).from(Foo))
132+
.to.eql(SELECT.columns('*','a',{b:'c'}).from(Foo))
133+
.to.eql(SELECT.columns(['*','a',{b:'c'}]).from(Foo))
134+
.to.eql(SELECT.columns((foo) => { foo`.*`, foo.a, foo.b`as c` }).from(Foo))
135+
.to.eql(SELECT.columns((foo) => { foo('*'), foo.a, foo.b.as('c') }).from(Foo))
136+
.to.eql(SELECT.from(Foo).columns('*','a',{b:'c'}))
137+
.to.eql(SELECT.from(Foo).columns(['*','a',{b:'c'}]))
138+
.to.eql(SELECT.from(Foo).columns((foo) => { foo`.*`, foo.a, foo.b`as c` }))
139+
.to.eql(SELECT.from(Foo).columns((foo) => { foo('*'), foo.a, foo.b.as('c') }))
140+
.to.eql(SELECT.from(Foo,['*','a',{b:'c'}]))
141+
.to.eql(SELECT.from(Foo, (foo) => { foo`.*`, foo.a, foo.b`as c` }))
142+
.to.eql(SELECT.from(Foo, (foo) => { foo('*'), foo.a, foo.b.as('c') }))
143+
144+
expect.plain(cqn)
145+
.to.eql({
120146
SELECT: {
121147
from: { ref: ['Foo'] },
122-
columns: [{ ref: ['a'] }, { ref: ['b'], as: 'c' }],
148+
columns: [ STAR, { ref: ['a'] }, { ref: ['b'], as: 'c' }],
123149
},
124150
})
125-
expect(SELECT.from(Foo, ['a', { b: 'c' }])).to.eql(cqn)
126-
expect(
127-
SELECT.from(Foo, (foo) => {
128-
foo.a, foo.b.as('c')
129-
})
130-
).to.eql(cqn)
131-
expect(SELECT.from(Foo).columns('a', { b: 'c' })).to.eql(cqn)
132-
expect(SELECT.from(Foo).columns(['a', { b: 'c' }])).to.eql(cqn)
133-
expect(
134-
SELECT.from(Foo).columns((foo) => {
135-
foo.a, foo.b.as('c')
136-
})
137-
).to.eql(cqn)
138-
139-
// multiple columns and *, prefix and postfix, as array and function
140-
expect(CQL`SELECT *,a,b from Foo`).to.eql(CQL`SELECT from Foo{*,a,b}`)
141-
//> .to.eql... FIXME: see skipped 'should handle * correctly' below
142-
expect(SELECT.from(Foo, ['a', 'b', '*']))
143-
.to.eql(SELECT.from(Foo).columns('a', 'b', '*'))
144-
.to.eql(SELECT.from(Foo).columns(['a', 'b', '*']))
145-
.to.eql(
146-
SELECT.from(Foo, (foo) => {
147-
foo.a, foo.b, foo('*')
148-
})
149-
)
151+
152+
cdr && expect.plain(cqn)
153+
.to.eql(CQL`SELECT *,a,b as c from Foo`)
154+
.to.eql(CQL`SELECT from Foo {*,a,b as c}`)
155+
156+
// Test combination with key as second argument to .from
157+
expect(cqn = SELECT.from(Foo, 11, ['a']))
158+
.to.eql(SELECT.from(Foo, 11, foo => foo.a))
159+
expect.one(cqn)
150160
.to.eql({
151161
SELECT: {
162+
one: true,
152163
from: { ref: ['Foo'] },
153-
columns: [{ ref: ['a'] }, { ref: ['b'] }, cdr ? '*' : { ref: ['*'] }],
164+
columns: [{ ref: ['a'] }],
165+
where: [{ ref: ['ID'] }, '=', { val: 11 }],
154166
},
155167
})
168+
156169
})
157170

158-
test('from ( ..., => _.expand ( x=>{...}))', () => {
171+
test('with nested expands', () => {
159172
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
160-
expect(
161-
SELECT.from(Foo, (foo) => {
162-
foo('*'),
163-
foo.x,
164-
foo.car('*'),
165-
foo.boo((b) => {
166-
b('*'), b.moo.zoo((x) => x.y.z)
167-
})
173+
expect(cqn =
174+
SELECT.from (Foo, foo => {
175+
foo`*`, foo.x, foo.car`*`, foo.boo (b => {
176+
b`*`, b.moo.zoo(
177+
x => x.y.z
178+
)
179+
})
168180
})
169-
).to.eql({
181+
).to.eql(
182+
SELECT.from (Foo, foo => {
183+
foo('*'), foo.x, foo.car('*'), foo.boo (b => {
184+
b('*'), b.moo.zoo(
185+
x => x.y.z
186+
)
187+
})
188+
})
189+
)
190+
191+
expect.plain(cqn)
192+
.to.eql({
170193
SELECT: {
171194
from: { ref: ['Foo'] },
172195
columns: [
173-
cdr ? '*' : { ref: ['*'] },
196+
STAR,
174197
{ ref: ['x'] },
175198
{ ref: ['car'], expand: ['*'] },
176199
{
177200
ref: ['boo'],
178-
expand: ['*', { ref: ['moo', 'zoo'], expand: [{ ref: ['y', 'z'] }] }],
201+
expand: [ '*', { ref: ['moo', 'zoo'], expand: [{ ref: ['y', 'z'] }] }],
179202
},
180203
],
181204
},
182205
})
183206
})
184207

185-
test('from ( ..., => _.inline ( _=>{...}))', () => {
208+
if (each !== 'SELECT') return
209+
210+
test('with nested inlines', () => {
186211
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
187212
expect(
188-
SELECT.from(Foo, (foo) => {
189-
foo.bar('*'),
190-
foo.bar('.*'), //> leading dot indicates inline
191-
foo.boo((x) => x.moo.zoo),
192-
foo.boo((_) => _.moo.zoo) //> underscore arg name indicates inline
213+
SELECT.from (Foo, foo => {
214+
foo.bar `*`,
215+
foo.bar `.*`, //> leading dot indicates inline
216+
foo.boo(_ => _.moo.zoo), //> underscore arg name indicates inline
217+
foo.boo(x => x.moo.zoo)
193218
})
194219
).to.eql({
195220
SELECT: {
196221
from: { ref: ['Foo'] },
197222
columns: [
198223
{ ref: ['bar'], expand: ['*'] },
199224
{ ref: ['bar'], inline: ['*'] },
200-
{ ref: ['boo'], expand: [{ ref: ['moo', 'zoo'] }] },
201225
{ ref: ['boo'], inline: [{ ref: ['moo', 'zoo'] }] },
226+
{ ref: ['boo'], expand: [{ ref: ['moo', 'zoo'] }] },
202227
],
203228
},
204229
})
205230
})
206231

207-
test('one / distinct ...', () => {
208-
expect(SELECT.distinct.from(Foo).SELECT)
209-
// .to.eql(CQL(`SELECT distinct from Foo`).SELECT)
210-
.to.eql(SELECT.distinct(Foo).SELECT)
211-
.to.eql({ distinct: true, from: { ref: ['Foo'] } })
212-
213-
expect(SELECT.one.from(Foo).SELECT)
214-
// .to.eql(CQL(`SELECT one from Foo`).SELECT)
215-
.to.eql(SELECT.one(Foo).SELECT)
216-
.to.eql({ one: true, from: { ref: ['Foo'] } })
217-
218-
expect(SELECT.one('a').from(Foo).SELECT)
219-
// .to.eql(CQL(`SELECT distinct a from Foo`).SELECT)
220-
.to.eql(SELECT.one(['a']).from(Foo).SELECT)
221-
.to.eql(SELECT.one(Foo, ['a']).SELECT)
222-
.to.eql(SELECT.one(Foo, (foo) => foo.a).SELECT)
223-
.to.eql(SELECT.one.from(Foo, (foo) => foo.a).SELECT)
224-
.to.eql(SELECT.one.from(Foo, ['a']).SELECT)
225-
.to.eql({
226-
one: true,
227-
from: { ref: ['Foo'] },
228-
columns: [{ ref: ['a'] }],
229-
})
230-
// same for works distinct
231-
})
232-
233232
it('should correctly handle { ... and:{...} }', () => {
234233
expect(SELECT.from(Foo).where({ x: 1, and: { y: 2, or: { z: 3 } } })).to.eql({
235234
SELECT: {
@@ -427,6 +426,7 @@ describe('cds.ql → cqn', () => {
427426

428427
//
429428
})
429+
}
430430

431431
describe(`INSERT...`, () => {
432432
test('entries ({a,b}, ...)', () => {

0 commit comments

Comments
 (0)