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 <chgeo@users.noreply.github.com>
This commit is contained in:
@@ -12,8 +12,7 @@
|
||||
"@capire/media": "./media",
|
||||
"@capire/orders": "./orders",
|
||||
"@capire/reviews": "./reviews",
|
||||
"@sap/cds": "^5",
|
||||
"express": "^4"
|
||||
"@sap/cds": "^5.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cds-swagger-ui-express": "^0.2.0",
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
const cds = require('@sap/cds/lib')
|
||||
const { expect } = cds.test
|
||||
const CQL = ([cql]) => cds.parse.cql(cql)
|
||||
const { cdr } = cds.ql
|
||||
const Foo = { name: 'Foo' }
|
||||
const Books = { name: 'capire.bookshop.Books' }
|
||||
|
||||
const { cdr } = cds.ql
|
||||
|
||||
// while jest has 'test' as alias to 'it', mocha doesn't
|
||||
if (!global.test) global.test = it
|
||||
const STAR = cdr ? '*' : { ref: ['*'] }
|
||||
const skip = {to:{eql:()=>skip}}
|
||||
const srv = new cds.Service
|
||||
let cqn
|
||||
|
||||
expect.plain = (cqn) => !cqn.SELECT.one && !cqn.SELECT.distinct ? expect(cqn) : skip
|
||||
expect.one = (cqn) => !cqn.SELECT.distinct ? expect(cqn) : skip
|
||||
|
||||
describe('cds.ql → cqn', () => {
|
||||
//
|
||||
let cqn
|
||||
|
||||
describe(`SELECT...`, () => {
|
||||
|
||||
@@ -26,170 +29,192 @@ describe('cds.ql → cqn', () => {
|
||||
.to.eql(SELECT.from(Foo,['*']))
|
||||
})
|
||||
|
||||
test('from ( Foo )', () => {
|
||||
expect({
|
||||
|
||||
it('should consistently handle lists', () => {
|
||||
const ID = 11, args = [{ref:['foo']}, 'bar', 3]
|
||||
const cqn = CQL`SELECT from Foo where ID=11 and x in (foo,'bar',3)`
|
||||
expect(SELECT.from`Foo`.where `ID=${ID} and x in ${args}`).to.eql(cqn)
|
||||
expect(SELECT.from(Foo).where(`ID=`, ID, `and x in`, args)).to.eql(cqn)
|
||||
expect(SELECT.from(Foo).where({ ID, x:args })).to.eql(cqn)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
for (let each of ['SELECT', 'SELECT one', 'SELECT distinct']) {
|
||||
let SELECT; beforeEach(()=> SELECT = (
|
||||
each === 'SELECT distinct' ? cds.ql.SELECT.distinct :
|
||||
each === 'SELECT one' ? cds.ql.SELECT.one :
|
||||
cds.ql.SELECT
|
||||
))
|
||||
describe(`${each}...`, () => {
|
||||
|
||||
test(`from Foo`, () => {
|
||||
expect(cqn = SELECT `from Foo`)
|
||||
.to.eql(SELECT.from `Foo`)
|
||||
.to.eql(SELECT.from('Foo'))
|
||||
.to.eql(SELECT.from(Foo))
|
||||
.to.eql(SELECT`Foo`)
|
||||
.to.eql(SELECT('Foo'))
|
||||
.to.eql(SELECT(Foo))
|
||||
expect.plain(cqn)
|
||||
.to.eql(CQL`SELECT from Foo`)
|
||||
.to.eql(srv.read `Foo`)
|
||||
.to.eql(srv.read('Foo'))
|
||||
.to.eql(srv.read(Foo))
|
||||
.to.eql({
|
||||
SELECT: { from: { ref: ['Foo'] } },
|
||||
})
|
||||
.to.eql(CQL`SELECT from Foo`)
|
||||
.to.eql(SELECT.from(Foo))
|
||||
})
|
||||
|
||||
test('from ( ..., <key>)', () => {
|
||||
// Compiler
|
||||
expect(CQL`SELECT from Foo[11]`).to.eql({
|
||||
SELECT: {
|
||||
// REVISIT: add one:true?
|
||||
from: { ref: [{ id: 'Foo', where: [{ val: 11 }] }] },
|
||||
},
|
||||
|
||||
test('from Foo [<key>]', () => {
|
||||
|
||||
expect(cqn = SELECT`from Foo[11]`)
|
||||
.to.eql(SELECT`from Foo[${11}]`)
|
||||
.to.eql(SELECT.from `Foo[11]`)
|
||||
.to.eql(SELECT.from `Foo[${11}]`)
|
||||
.to.eql(SELECT`Foo[11]`)
|
||||
expect.plain(cqn)
|
||||
.to.eql(CQL`SELECT from Foo[11]`)
|
||||
.to.eql(srv.read`Foo[11]`)
|
||||
.to.eql({
|
||||
SELECT: { from: {
|
||||
ref: [{ id: 'Foo', where: [{ val: 11 }] }]
|
||||
}},
|
||||
})
|
||||
|
||||
expect(CQL`SELECT from Foo[ID=11]`).to.eql({
|
||||
SELECT: {
|
||||
// REVISIT: add one:true
|
||||
from: {
|
||||
ref: [{ id: 'Foo', where: [{ ref: ['ID'] }, '=', { val: 11 }] }],
|
||||
},
|
||||
},
|
||||
if (cdr) expect.plain (cqn)
|
||||
.to.eql(srv.read`Foo[${11}]`)
|
||||
.to.eql(SELECT`Foo[${11}]`)
|
||||
|
||||
expect((cqn = SELECT`from Foo[ID=11]`))
|
||||
.to.eql(SELECT`from Foo[ID=${11}]`)
|
||||
.to.eql(SELECT.from `Foo[ID=11]`)
|
||||
.to.eql(SELECT.from `Foo[ID=${11}]`)
|
||||
.to.eql(SELECT`Foo[ID=11]`)
|
||||
expect.plain(cqn)
|
||||
.to.eql(CQL`SELECT from Foo[ID=11]`)
|
||||
.to.eql(srv.read`Foo[ID=11]`)
|
||||
.to.eql({
|
||||
SELECT: { from: {
|
||||
ref: [{ id: 'Foo', where: [{ ref: ['ID'] }, '=', { val: 11 }] }],
|
||||
}},
|
||||
})
|
||||
|
||||
// Runtime ds.ql
|
||||
expect(SELECT.from(Foo, 11))
|
||||
.to.eql(SELECT.from(Foo, { ID: 11 }))
|
||||
.to.eql(SELECT.from(Foo).byKey(11))
|
||||
.to.eql(SELECT.from(Foo).byKey({ ID: 11 }))
|
||||
.to.eql(SELECT.one.from(Foo).where({ ID: 11 }))
|
||||
.to.eql({
|
||||
// REVISIT: should produce CQN as the ones above?
|
||||
SELECT: {
|
||||
one: true,
|
||||
from: { ref: ['Foo'] },
|
||||
where: [{ ref: ['ID'] }, '=', { val: 11 }],
|
||||
},
|
||||
})
|
||||
if (cdr) expect.plain (cqn)
|
||||
.to.eql(SELECT`Foo[ID=${11}]`)
|
||||
.to.eql(srv.read`Foo[ID=${11}]`)
|
||||
|
||||
expect(CQL`SELECT from Foo[11]{a}`).to.eql({
|
||||
SELECT: {
|
||||
// REVISIT: add one:true?
|
||||
from: { ref: [{ id: 'Foo', where: [{ val: 11 }] }] },
|
||||
columns: [{ ref: ['a'] }],
|
||||
},
|
||||
})
|
||||
|
||||
expect(SELECT.from(Foo, 11, ['a']))
|
||||
.to.eql(SELECT.from(Foo, 11, (foo) => foo.a))
|
||||
.to.eql({
|
||||
// REVISIT: should produce CQN as the ones above?
|
||||
SELECT: {
|
||||
one: true,
|
||||
from: { ref: ['Foo'] },
|
||||
columns: [{ ref: ['a'] }],
|
||||
where: [{ ref: ['ID'] }, '=', { val: 11 }],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('from ( ..., => {...})', () => {
|
||||
// single *, prefix and postfix, as array and function
|
||||
let parsed, fluid
|
||||
expect((parsed = CQL`SELECT * from Foo`)).to.eql(CQL`SELECT from Foo{*}`)
|
||||
//> .to.eql... FIXME: see skipped 'should handle * correctly' below
|
||||
expect((fluid = SELECT('*').from(Foo)))
|
||||
.to.eql(SELECT.from(Foo, ['*']))
|
||||
.to.eql(SELECT.from(Foo, (foo) => foo('*')))
|
||||
.to.eql(SELECT.from(Foo).columns('*'))
|
||||
.to.eql(SELECT.from(Foo).columns((foo) => foo('*')))
|
||||
.to.eql({
|
||||
SELECT: { from: { ref: ['Foo'] }, columns: [cdr ? '*' : { ref: ['*'] }] },
|
||||
})
|
||||
|
||||
if (cdr === 'all') expect(parsed).to.eql(fluid)
|
||||
|
||||
// single column, prefix and postfix, as array and function
|
||||
expect(CQL`SELECT a from Foo`)
|
||||
expect(CQL`SELECT from Foo {a}`)
|
||||
.to.eql(SELECT.from(Foo, ['a']))
|
||||
.to.eql(SELECT.from(Foo, (foo) => foo.a))
|
||||
.to.eql({
|
||||
SELECT: { from: { ref: ['Foo'] }, columns: [{ ref: ['a'] }] },
|
||||
})
|
||||
|
||||
// multiple columns, prefix and postfix, as array and function
|
||||
expect(CQL`SELECT a,b as c from Foo`)
|
||||
|
||||
expect (CQL`SELECT from Foo {a,b as c}`).to.eql(cqn = {
|
||||
// Following implicitly resolve to SELECT.one
|
||||
expect(cqn = SELECT.from(Foo,11))
|
||||
.to.eql(SELECT.from(Foo,{ID:11}))
|
||||
.to.eql(SELECT.from(Foo).byKey(11))
|
||||
.to.eql(SELECT.from(Foo).byKey({ID:11}))
|
||||
expect.one(cqn)
|
||||
.to.eql({
|
||||
SELECT: {
|
||||
one: true,
|
||||
from: { ref: ['Foo'] },
|
||||
columns: [{ ref: ['a'] }, { ref: ['b'], as: 'c' }],
|
||||
where: [{ ref: ['ID'] }, '=', { val: 11 }],
|
||||
},
|
||||
})
|
||||
expect(SELECT.from(Foo, ['a', { b: 'c' }])).to.eql(cqn)
|
||||
expect(
|
||||
SELECT.from(Foo, (foo) => {
|
||||
foo.a, foo.b.as('c')
|
||||
})
|
||||
).to.eql(cqn)
|
||||
expect(SELECT.from(Foo).columns('a', { b: 'c' })).to.eql(cqn)
|
||||
expect(SELECT.from(Foo).columns(['a', { b: 'c' }])).to.eql(cqn)
|
||||
expect(
|
||||
SELECT.from(Foo).columns((foo) => {
|
||||
foo.a, foo.b.as('c')
|
||||
})
|
||||
).to.eql(cqn)
|
||||
|
||||
// multiple columns and *, prefix and postfix, as array and function
|
||||
expect(CQL`SELECT *,a,b from Foo`).to.eql(CQL`SELECT from Foo{*,a,b}`)
|
||||
//> .to.eql... FIXME: see skipped 'should handle * correctly' below
|
||||
expect(SELECT.from(Foo, ['a', 'b', '*']))
|
||||
.to.eql(SELECT.from(Foo).columns('a', 'b', '*'))
|
||||
.to.eql(SELECT.from(Foo).columns(['a', 'b', '*']))
|
||||
.to.eql(
|
||||
SELECT.from(Foo, (foo) => {
|
||||
foo.a, foo.b, foo('*')
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test('from Foo {...}', () => {
|
||||
|
||||
expect(cqn = SELECT `*,a,b as c` .from `Foo`)
|
||||
.to.eql(SELECT `*,a,b as c`. from(Foo))
|
||||
.to.eql(SELECT('*','a',{b:'c'}).from`Foo`)
|
||||
.to.eql(SELECT('*','a',{b:'c'}).from(Foo))
|
||||
.to.eql(SELECT(['*','a',{b:'c'}]).from(Foo))
|
||||
.to.eql(SELECT.columns('*','a',{b:'c'}).from(Foo))
|
||||
.to.eql(SELECT.columns(['*','a',{b:'c'}]).from(Foo))
|
||||
.to.eql(SELECT.columns((foo) => { foo`.*`, foo.a, foo.b`as c` }).from(Foo))
|
||||
.to.eql(SELECT.columns((foo) => { foo('*'), foo.a, foo.b.as('c') }).from(Foo))
|
||||
.to.eql(SELECT.from(Foo).columns('*','a',{b:'c'}))
|
||||
.to.eql(SELECT.from(Foo).columns(['*','a',{b:'c'}]))
|
||||
.to.eql(SELECT.from(Foo).columns((foo) => { foo`.*`, foo.a, foo.b`as c` }))
|
||||
.to.eql(SELECT.from(Foo).columns((foo) => { foo('*'), foo.a, foo.b.as('c') }))
|
||||
.to.eql(SELECT.from(Foo,['*','a',{b:'c'}]))
|
||||
.to.eql(SELECT.from(Foo, (foo) => { foo`.*`, foo.a, foo.b`as c` }))
|
||||
.to.eql(SELECT.from(Foo, (foo) => { foo('*'), foo.a, foo.b.as('c') }))
|
||||
|
||||
expect.plain(cqn)
|
||||
.to.eql({
|
||||
SELECT: {
|
||||
from: { ref: ['Foo'] },
|
||||
columns: [{ ref: ['a'] }, { ref: ['b'] }, cdr ? '*' : { ref: ['*'] }],
|
||||
columns: [ STAR, { ref: ['a'] }, { ref: ['b'], as: 'c' }],
|
||||
},
|
||||
})
|
||||
|
||||
cdr && expect.plain(cqn)
|
||||
.to.eql(CQL`SELECT *,a,b as c from Foo`)
|
||||
.to.eql(CQL`SELECT from Foo {*,a,b as c}`)
|
||||
|
||||
// Test combination with key as second argument to .from
|
||||
expect(cqn = SELECT.from(Foo, 11, ['a']))
|
||||
.to.eql(SELECT.from(Foo, 11, foo => foo.a))
|
||||
expect.one(cqn)
|
||||
.to.eql({
|
||||
SELECT: {
|
||||
one: true,
|
||||
from: { ref: ['Foo'] },
|
||||
columns: [{ ref: ['a'] }],
|
||||
where: [{ ref: ['ID'] }, '=', { val: 11 }],
|
||||
},
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
test('from ( ..., => _.expand ( x=>{...}))', () => {
|
||||
test('with nested expands', () => {
|
||||
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
|
||||
expect(
|
||||
SELECT.from(Foo, (foo) => {
|
||||
foo('*'),
|
||||
foo.x,
|
||||
foo.car('*'),
|
||||
foo.boo((b) => {
|
||||
b('*'), b.moo.zoo((x) => x.y.z)
|
||||
})
|
||||
expect(cqn =
|
||||
SELECT.from (Foo, foo => {
|
||||
foo`*`, foo.x, foo.car`*`, foo.boo (b => {
|
||||
b`*`, b.moo.zoo(
|
||||
x => x.y.z
|
||||
)
|
||||
})
|
||||
})
|
||||
).to.eql({
|
||||
).to.eql(
|
||||
SELECT.from (Foo, foo => {
|
||||
foo('*'), foo.x, foo.car('*'), foo.boo (b => {
|
||||
b('*'), b.moo.zoo(
|
||||
x => x.y.z
|
||||
)
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
expect.plain(cqn)
|
||||
.to.eql({
|
||||
SELECT: {
|
||||
from: { ref: ['Foo'] },
|
||||
columns: [
|
||||
cdr ? '*' : { ref: ['*'] },
|
||||
STAR,
|
||||
{ ref: ['x'] },
|
||||
{ ref: ['car'], expand: ['*'] },
|
||||
{
|
||||
ref: ['boo'],
|
||||
expand: ['*', { ref: ['moo', 'zoo'], expand: [{ ref: ['y', 'z'] }] }],
|
||||
expand: [ '*', { ref: ['moo', 'zoo'], expand: [{ ref: ['y', 'z'] }] }],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('from ( ..., => _.inline ( _=>{...}))', () => {
|
||||
if (each !== 'SELECT') return
|
||||
|
||||
test('with nested inlines', () => {
|
||||
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
|
||||
expect(
|
||||
SELECT.from(Foo, (foo) => {
|
||||
foo.bar('*'),
|
||||
foo.bar('.*'), //> leading dot indicates inline
|
||||
foo.boo((x) => x.moo.zoo),
|
||||
foo.boo((_) => _.moo.zoo) //> underscore arg name indicates inline
|
||||
SELECT.from (Foo, foo => {
|
||||
foo.bar `*`,
|
||||
foo.bar `.*`, //> leading dot indicates inline
|
||||
foo.boo(_ => _.moo.zoo), //> underscore arg name indicates inline
|
||||
foo.boo(x => x.moo.zoo)
|
||||
})
|
||||
).to.eql({
|
||||
SELECT: {
|
||||
@@ -197,39 +222,13 @@ describe('cds.ql → cqn', () => {
|
||||
columns: [
|
||||
{ ref: ['bar'], expand: ['*'] },
|
||||
{ ref: ['bar'], inline: ['*'] },
|
||||
{ ref: ['boo'], expand: [{ ref: ['moo', 'zoo'] }] },
|
||||
{ ref: ['boo'], inline: [{ ref: ['moo', 'zoo'] }] },
|
||||
{ ref: ['boo'], expand: [{ ref: ['moo', 'zoo'] }] },
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('one / distinct ...', () => {
|
||||
expect(SELECT.distinct.from(Foo).SELECT)
|
||||
// .to.eql(CQL(`SELECT distinct from Foo`).SELECT)
|
||||
.to.eql(SELECT.distinct(Foo).SELECT)
|
||||
.to.eql({ distinct: true, from: { ref: ['Foo'] } })
|
||||
|
||||
expect(SELECT.one.from(Foo).SELECT)
|
||||
// .to.eql(CQL(`SELECT one from Foo`).SELECT)
|
||||
.to.eql(SELECT.one(Foo).SELECT)
|
||||
.to.eql({ one: true, from: { ref: ['Foo'] } })
|
||||
|
||||
expect(SELECT.one('a').from(Foo).SELECT)
|
||||
// .to.eql(CQL(`SELECT distinct a from Foo`).SELECT)
|
||||
.to.eql(SELECT.one(['a']).from(Foo).SELECT)
|
||||
.to.eql(SELECT.one(Foo, ['a']).SELECT)
|
||||
.to.eql(SELECT.one(Foo, (foo) => foo.a).SELECT)
|
||||
.to.eql(SELECT.one.from(Foo, (foo) => foo.a).SELECT)
|
||||
.to.eql(SELECT.one.from(Foo, ['a']).SELECT)
|
||||
.to.eql({
|
||||
one: true,
|
||||
from: { ref: ['Foo'] },
|
||||
columns: [{ ref: ['a'] }],
|
||||
})
|
||||
// same for works distinct
|
||||
})
|
||||
|
||||
it('should correctly handle { ... and:{...} }', () => {
|
||||
expect(SELECT.from(Foo).where({ x: 1, and: { y: 2, or: { z: 3 } } })).to.eql({
|
||||
SELECT: {
|
||||
@@ -427,6 +426,7 @@ describe('cds.ql → cqn', () => {
|
||||
|
||||
//
|
||||
})
|
||||
}
|
||||
|
||||
describe(`INSERT...`, () => {
|
||||
test('entries ({a,b}, ...)', () => {
|
||||
|
||||
@@ -15,17 +15,17 @@ describe('Consuming Services locally', () => {
|
||||
it('supports targets as strings or reflected defs', async () => {
|
||||
const AdminService = await cds.connect.to('AdminService')
|
||||
const { Authors } = AdminService.entities
|
||||
const _ = expect (await AdminService.read(Authors))
|
||||
expect (await SELECT.from(Authors))
|
||||
.to.eql(await SELECT.from('Authors'))
|
||||
.to.eql(await AdminService.read(Authors))
|
||||
.to.eql(await AdminService.read('Authors'))
|
||||
.to.eql(await AdminService.run(SELECT.from(Authors)))
|
||||
// temporary workaround
|
||||
if (cds.version >= '4.2.0')
|
||||
_.to.eql(await AdminService.run(SELECT.from('Authors')))
|
||||
.to.eql(await AdminService.run(SELECT.from('Authors')))
|
||||
})
|
||||
|
||||
it('allows reading from local services using cds.ql', async () => {
|
||||
const AdminService = await cds.connect.to('AdminService')
|
||||
const query = SELECT.from('Authors', (a) => {
|
||||
const authors = await AdminService.read (`Authors`, a => {
|
||||
a.name,
|
||||
a.books((b) => {
|
||||
b.title,
|
||||
@@ -34,10 +34,6 @@ describe('Consuming Services locally', () => {
|
||||
})
|
||||
})
|
||||
}).where(`name like`, 'E%')
|
||||
// temporary workaround
|
||||
if (cds.version < '4.2.0')
|
||||
query.SELECT.from.ref[0] = 'AdminService.Authors'
|
||||
const authors = await AdminService.run(query)
|
||||
expect(authors).to.containSubset([
|
||||
{
|
||||
name: 'Emily Brontë',
|
||||
|
||||
Reference in New Issue
Block a user