diff --git a/db-service/lib/assert-constraint.js b/db-service/lib/assert-constraint.js index ca8670d1e..f41e9d86f 100644 --- a/db-service/lib/assert-constraint.js +++ b/db-service/lib/assert-constraint.js @@ -62,13 +62,15 @@ function attachConstraints(_results, req) { const xpr = [] // if the element is nullable, we prepend xpr with ` IS NULL OR …` if (!element.notNull && !element.on) { + // if(element.on) --> REVISIT: HANA doesnt like this, what can we do to ensure nullability? + // xpr.unshift({ ...coalesce(condition.xpr) }, 'or') xpr.unshift({ ref: [element.name] }, 'is', 'null', 'or') } xpr.push({ xpr: condition.xpr }) return { // case … when … needed for hana compatibility // REVISIT: can we move workaround to HANAService only? - xpr: ['case', 'when', { xpr }, 'then', { val: true }, 'else', { val: false }, 'end'], + xpr: wrapInCaseWhen(xpr), as: name, cast: { type: 'cds.Boolean', @@ -139,6 +141,9 @@ function attachConstraints(_results, req) { function wrapInCaseWhen(xpr) { return ['case', 'when', { xpr }, 'then', { val: true }, 'else', { val: false }, 'end'] } + function coalesce(xpr) { + return { func: 'coalesce', args: [{ xpr }, { val: true }] } + } } async function checkConstraints(req) { diff --git a/test/bookshop/db/schema.cds b/test/bookshop/db/schema.cds index 2f7922e69..f7ff68386 100644 --- a/test/bookshop/db/schema.cds +++ b/test/bookshop/db/schema.cds @@ -17,15 +17,8 @@ entity Books : managed { message: 'The stock must be greater than or equal to 0', parameters: [] // to be inserted into the message } - // @assert.constraint : { - // condition: ( stock <= price ), - // message: 'The stock must be less than or equal to price', - // parameters: [] // to be inserted into the message - // } stock : Integer; price : Decimal; - // one of the tests inserts a very big decimal which - // collides with our constraint above :D dummyDecimal : Decimal; currency : Currency; image : LargeBinary @Core.MediaType: 'image/png'; @@ -55,9 +48,10 @@ entity Authors : managed { /** Hierarchically organized Code List for Genres */ entity Genres : sap.common.CodeList { key ID : Integer; + @assert.constraint: ( parent.name is not null) parent : Association to Genres; // make sure only our pre-defined genres are allowed - @assert.constraint: ( children.name in ( + @assert.constraint: ( ( children.ID is null ) or children.name in ( 'Fiction', 'Drama', 'Poetry', 'Fantasy', 'Science Fiction', 'Romance', 'Mystery', 'Thriller', 'Dystopia', 'Fairy Tale', 'Non-Fiction', 'Biography', 'Autobiography', 'Essay', 'Speech', diff --git a/test/scenarios/bookshop/assert-constraint.test.js b/test/scenarios/bookshop/assert-constraint.test.js index 7948dc873..1556bc16e 100644 --- a/test/scenarios/bookshop/assert-constraint.test.js +++ b/test/scenarios/bookshop/assert-constraint.test.js @@ -116,5 +116,14 @@ describe('Bookshop - assertions', () => { // both should have been created expect(genres).to.have.length(2) }) + + test('genre without children works', async () => { + await POST('admin/Genres', { + ID: 102, + name: 'Genre without children', + }, { auth: { username: 'alice' } }) + const genre = await SELECT.one.from(Genres).where({ ID: 102 }) + expect(genre).to.exist + }) }) })