diff --git a/db-service/lib/cqn4sql.js b/db-service/lib/cqn4sql.js index 561e2c606..21e929ac9 100644 --- a/db-service/lib/cqn4sql.js +++ b/db-service/lib/cqn4sql.js @@ -132,7 +132,9 @@ function cqn4sql(originalQuery, model) { const queryTarget = Object.values(inferred.sources)[0].definition const keys = Object.values(queryTarget.elements).filter(e => e.key === true) const primaryKey = { list: [] } - keys.forEach(k => { + keys + .filter(k => !k.virtual) // e.g. draft column `isActiveEntity` is virtual and key + .forEach(k => { // cqn4sql will add the table alias to the column later, no need to add it here subquery.SELECT.columns.push({ ref: [k.name] }) diff --git a/db-service/test/cqn4sql/UPDATE.test.js b/db-service/test/cqn4sql/UPDATE.test.js index 5dc37d8f2..dd0e123d0 100644 --- a/db-service/test/cqn4sql/UPDATE.test.js +++ b/db-service/test/cqn4sql/UPDATE.test.js @@ -110,7 +110,7 @@ describe('UPDATE', () => { left join bookshop.Books as books on books.author_ID = Authors.ID where books.title LIKE '%Heights%' ) - ` + `, ] expected.UPDATE.entity = { as: 'Authors2', @@ -169,3 +169,35 @@ describe('UPDATE', () => { expect(query.UPDATE).to.deep.equal(expected.UPDATE) }) }) +describe('UPDATE with path expression', () => { + let model + beforeAll(async () => { + model = cds.model = await cds.load(__dirname + '/model/update').then(cds.linked) + model = cds.compile.for.nodejs(model) + }) + + it('with path expressions with draft enabled entity', () => { + const { UPDATE } = cds.ql + let u = UPDATE.entity({ ref: ['bookshop.CatalogService.Books'] }).where(`author.name LIKE '%Bron%'`) + + let expected = UPDATE.entity({ ref: ['bookshop.CatalogService.Books'] }) + + // dont use virtual key `isActiveEntity` in `UPDATE … where () in ` + expected.UPDATE.where = [ + { list: [{ ref: ['Books2', 'ID'] }] }, + 'in', + CQL` + (SELECT Books.ID from bookshop.CatalogService.Books as Books + left join bookshop.CatalogService.Authors as author on author.ID = Books.author_ID + where author.name LIKE '%Bron%' + ) + `, + ] + expected.UPDATE.entity = { + as: 'Books2', + ref: ['bookshop.CatalogService.Books'], + } + let res = cqn4sql(u, model) + expect(JSON.parse(JSON.stringify(res))).to.deep.equal(JSON.parse(JSON.stringify(expected))) + }) +}) diff --git a/db-service/test/cqn4sql/model/update.cds b/db-service/test/cqn4sql/model/update.cds new file mode 100644 index 000000000..c8f7cc3bd --- /dev/null +++ b/db-service/test/cqn4sql/model/update.cds @@ -0,0 +1,23 @@ +// dont use virtual key `isActiveEntity` in `UPDATE … where () in ` +// in case of path expressions +namespace bookshop; + +entity Books { + key ID : Integer; + title : String; + stock : Integer; + author : Association to Authors; +} + +entity Authors { + key ID : Integer; + name : String; + alive : Boolean; +} + +service CatalogService { + @odata.draft.enabled + entity Books as projection on bookshop.Books; + + entity Authors as projection on bookshop.Authors; +} diff --git a/test/bookshop/srv/draft-enabled-service.cds b/test/bookshop/srv/draft-enabled-service.cds index 30bceb848..0629e098f 100644 --- a/test/bookshop/srv/draft-enabled-service.cds +++ b/test/bookshop/srv/draft-enabled-service.cds @@ -1,3 +1,4 @@ +using { sap.capire.bookshop as my } from '../db/schema'; service DraftService { @odata.draft.enabled entity DraftEnabledBooks @@ -5,4 +6,7 @@ service DraftService { key ID : Integer; title : String; } -} \ No newline at end of file + + @odata.draft.enabled + entity MoreDraftEnabledBooks as projection on my.Books; +} diff --git a/test/scenarios/bookshop/update.test.js b/test/scenarios/bookshop/update.test.js index 0eb66d705..f784b9ca9 100644 --- a/test/scenarios/bookshop/update.test.js +++ b/test/scenarios/bookshop/update.test.js @@ -149,4 +149,18 @@ describe('Bookshop - Update', () => { const res = await UPSERT.into('DraftService.DraftEnabledBooks').entries({ ID: 42, title: 'Foo' }) expect(res).to.equal(1) }) + + test('with path expressions on draft enabled service entity', async () => { + // make sure `isActiveEntity` is not used in `UPDATE … where () in ` + // as it is a virtual + const { MoreDraftEnabledBooks } = cds.entities('DraftService') + const updateRichardsBooks = UPDATE.entity(MoreDraftEnabledBooks) + .where(`author.name = 'Richard Carpenter'`) + .set('ID = 42') + const selectRichardsBooks = CQL`SELECT * FROM ${MoreDraftEnabledBooks} where author.name = 'Richard Carpenter'` + + await cds.run(updateRichardsBooks) + const afterUpdate = await cds.db.run(selectRichardsBooks) + expect(afterUpdate[0]).to.have.property('ID').that.equals(42) + }) })