diff --git a/db-service/lib/cqn4sql.js b/db-service/lib/cqn4sql.js index e75da05e1..f26685c17 100644 --- a/db-service/lib/cqn4sql.js +++ b/db-service/lib/cqn4sql.js @@ -134,7 +134,7 @@ function cqn4sql(originalQuery, model) { const primaryKey = { list: [] } for (const k of Object.keys(queryTarget.elements)) { const e = queryTarget.elements[k] - if (e.key === true && !e.virtual) { + if (e.key === true && !e.virtual && e.isAssociation !== true) { subquery.SELECT.columns.push({ ref: [e.name] }) primaryKey.list.push({ ref: [transformedFrom.as, e.name] }) } diff --git a/db-service/lib/infer/index.js b/db-service/lib/infer/index.js index e54117e96..8eb235919 100644 --- a/db-service/lib/infer/index.js +++ b/db-service/lib/infer/index.js @@ -963,7 +963,8 @@ function infer(originalQuery, model) { if (element.type !== 'cds.LargeBinary') { queryElements[k] = element } - if (isCalculatedOnRead(element)) { + // only relevant if we actually select the calculated element + if (originalQuery.SELECT && isCalculatedOnRead(element)) { linkCalculatedElement(element) } } diff --git a/db-service/test/cqn4sql/UPDATE.test.js b/db-service/test/cqn4sql/UPDATE.test.js index dd0e123d0..f87195035 100644 --- a/db-service/test/cqn4sql/UPDATE.test.js +++ b/db-service/test/cqn4sql/UPDATE.test.js @@ -200,4 +200,41 @@ describe('UPDATE with path expression', () => { let res = cqn4sql(u, model) expect(JSON.parse(JSON.stringify(res))).to.deep.equal(JSON.parse(JSON.stringify(expected))) }) + + it('path expression via calculated element leads to subquery if used in where', () => { + const q = UPDATE('bookshop.Orders.Items').set({ price: 5 }).where('price = 4.99') + + const res = cqn4sql(q, model) + + const expected = UPDATE.entity({ ref: ['bookshop.Orders.Items'] }).alias('Items2') + expected.UPDATE.where = [ + { + list: [{ ref: ['Items2', 'up__ID'] }, { ref: ['Items2', 'book_ID'] }], + }, + 'in', + cds.ql` + (SELECT + Items.up__ID, + Items.book_ID + FROM bookshop.Orders.Items AS Items + LEFT JOIN bookshop.Books AS book ON book.ID = Items.book_ID + WHERE (book.stock * 2) = 4.99 + ) + `, + ] + + expect(JSON.parse(JSON.stringify(res))).to.deep.equal(JSON.parse(JSON.stringify(expected))) + }) + + it('if there is no path expression in the where, we dont need subselect magic', () => { + const q = UPDATE('bookshop.Orders.Items').set({ quantity: 3 }).where('1 = 1') + const res = cqn4sql(q, model) + expect(JSON.parse(JSON.stringify(res))).to.eql({ + UPDATE: { + entity: { ref: ['bookshop.Orders.Items'], as: 'Items' }, + where: [{ val: 1 }, '=', { val: 1 }], + }, + }) + expect(res.UPDATE).to.have.property('data') + }) }) diff --git a/db-service/test/cqn4sql/model/update.cds b/db-service/test/cqn4sql/model/update.cds index c8f7cc3bd..b221cfabf 100644 --- a/db-service/test/cqn4sql/model/update.cds +++ b/db-service/test/cqn4sql/model/update.cds @@ -15,6 +15,14 @@ entity Authors { alive : Boolean; } +entity Orders { + key ID: UUID; + Items: composition of many { + key book: Association to Books; + price: Decimal = book.stock * 2; + } +} + service CatalogService { @odata.draft.enabled entity Books as projection on bookshop.Books;